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

最近在写一个同父类不同子类的处理方法,例如最简单的处理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.0
kite  prints Long : 323
lucy  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;
}
 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值