首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

用注解的方式来解决不同子类的处理有关问题

2012-09-08 
用注解的方式来解决不同子类的处理问题最近在写一个同父类不同子类的处理方法,例如最简单的处理Number类的

用注解的方式来解决不同子类的处理问题

最近在写一个同父类不同子类的处理方法,例如最简单的处理Number类的时候,假设返回值有不同类型,

如Long,Double,Integer等,并且需要对这些类型有不同的处理方式的时候,一般的情况下,我们可以使用下面这种方式来处理:

?

?

if( object instanceof  Long){     //do long}else if(object instanceof Double){    //do double}else if(object instanceof Integer){   // do Integer}
?

简单的方式就可以区分不同子类类型的处理方式了。

不过这种方式很显然有个缺点,如果需要增加处理新的子类型的时候,需要修改到原有的判断逻辑,如加上

?

if( object instanceof  Long){     //do long}else if(object instanceof Double){    //do double}else if(object instanceof Integer){   // do Integer}else if(object instanceof Float){  // do Float}

?修改原有逻辑有风险,那么有没有其他方式可以既不修改原有的调用方式,同时可以满足处理新增子类型的需求呢?

?

?我们可以试下用注解的方式,如下面代码

?

public class MethodInvokerDemo {    /**     * 测试类     *      */    public static class A extends MethodInvoker {        public void print(Number number, String userName) {            String result = (String) invoke(number, userName);            System.out.println(result);        }        @Invoke(classType = Double.class)        protected String printDouble(Double obj, String userName) {            return userName + "  prints Double : " + obj;        }        @Invoke(classType = Long.class)        protected String printLong(Long obj, String userName) {            return userName + "  prints Long : " + obj;        }        @Invoke(classType = Integer.class)        protected String printInteger(Integer obj, String userName) {            return userName + "  prints Integer : " + obj;        }    }    /**     * 测试入口     *      * @param args     */    public static void main(String[] args) {        A test = new A();       test.print(1.0, "lily");       test.print(323L, "kite");       test.print(5, "lucy");    }}

?

?

? ?最后的结果如下:

?

lily  prints Double : 1.0kite  prints Long : 323lucy  prints Integer : 5

?

?

? ?我们可以看下具体是怎么实现的,下面是MethodInvoker的实现代码:

?

public class MethodInvoker {    /**     * 内部方法注解,标记方法和对应处理的类类型     * 使用方式:@Invoke( classType = Number.class)       */    @Target(ElementType.METHOD)    @Retention(RetentionPolicy.RUNTIME)    public @interface Invoke {        /**         * 类类型         *          * @return         */        public Class<?> classType() default Object.class;    }    /**     * 根据子类的注解调用对应的方法,如 invoke(new Long(1L));     * 则调用@Invoke(classType=Long.class)对应方法     *  参数类型和个数必须匹配 举例:<br>     *      * @param obj     * @param parameters     * @return     */    protected final Object invoke(Object obj, Object... parameters) {        if (obj == null) {            return null;        }        this.refresh();        // 取出所有参数,拼装成参数数组        Object[] allParams = new Object[1 +                     (parameters == null ? 0 : parameters.length)];        if (parameters != null && parameters.length != 0) {            for (int i = 1; i < allParams.length; i++) {                allParams[i] = parameters[i - 1];            }        }        allParams[0] = obj;        // 取出缓存的方法表        Method method = this.typeMethodMap.get(obj.getClass().getName());        if (method == null) {            String className = obj.getClass().getSimpleName() + ".class";            throw new RuntimeException("can not find method for annotation @Invoke(classType=" + className + ")");        }        // 设置调用权限为public        try {            method.setAccessible(true);        } catch (Exception es) {            // do nothing        }        // 调用该方法并返回结果        try {            return method.invoke(this, allParams);        } catch (Exception e) {            String methodName = this.getClass().getName() + "." + method.getName();            throw new RuntimeException("execute " + methodName + " failed :" + e.getMessage(), e);        }    }    /**     * 刷新注解和方法的绑定关系     *      */    private void refresh() {        if (!typeMethodMap.isEmpty()) {            return;        }        Map<String, Method> tmpMap = new ConcurrentHashMap<String, Method>();        Method[] methods = this.getClass().getDeclaredMethods();        if (methods != null && methods.length != 0) {            for (Method method : methods) {                Invoke invoke = method.getAnnotation(Invoke.class);                if (invoke == null) {                    continue;                }                tmpMap.put(invoke.classType().getName(), method);            }        }        typeMethodMap = tmpMap;    }    /**     * 子类<注解对应的类名称,方法对象>缓存表     */    private Map<String, Method> typeMethodMap = new ConcurrentHashMap<String, Method>();}
?

?

? ?简单的继承MethodInvoker即可实现不同的子类使用不同的处理类型,并且不需要修改原有代码了,

? ?如需要新增处理Float类型,我们只需要增加这个方法:

?

@Invoke(classType = Float.class)    protected String printInteger(Float obj, String userName) {        return userName + "  prints Float: " + obj;}
?

?

?

?

?

?

注解妙用~

热点排行