JAVA反射实现委托模型(方法可以传入参数)

    委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用聚合来替代继承.

    在C#中,委托由delegate实现,在Java中并没有委托机制,所以我们可以选择用反射来实现委托,下面看看具体的代码.

通知者(主题)实现:

package 事件委托模式;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 主题类
 * 在订阅了主题后(将需要执行的方法或者参数加入主题后),在主题发出响应时,可以自动执行set中的方法.
 */
public class Subject {

    private final Set<ObjectMethodAndParameters> set = new HashSet<>();

    /**
     * 将一个需要执行的对象以及方法加入到主题的集合中
     * @param obj 需要执行的对象
     * @param methodName 需要执行的方法名称
     * @param parameterizedTypes 需要执行的方法的参数类型
     * @param params 需要执行的方法的具体参数
     */
    public void Attach(Object obj, String methodName,Class<?>[] parameterizedTypes,Object[] params) {
        ObjectMethodAndParameters objectMethodAndParameters = new ObjectMethodAndParameters(obj, methodName, parameterizedTypes,params);
        set.add(objectMethodAndParameters);
    }

    /**
     * 将一个需要执行的对象以及方法从主题中删除
     * @param obj 需要执行的对象
     * @param methodName 需要执行的方法名称
     * @param parameterizedTypes 需要执行的方法的参数类型
     * @param params 需要执行的方法的具体参数
     */
    public void Detach(Object obj,String methodName,Class<?>[] parameterizedTypes,Object[] params) {
        ObjectMethodAndParameters object = new ObjectMethodAndParameters(obj, methodName, parameterizedTypes,params);
        set.removeIf(next -> next.equals(object));
    }

    /**
     * 执行所有订阅了主题的方法
     * @throws NoSuchMethodException 没有找到对应的方法
     * @throws InvocationTargetException 被调用的方法或构造函数引发的异常
     * @throws IllegalAccessException 对应方法因权限问题不允许方法
     */
    public void NotifyAll() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        for (ObjectMethodAndParameters next : set) {
            //获取需要执行的对象本体,需要执行的方法名称,以及参数类型
            Object object = next.getObject();
            String methodName = next.getMethodName();
            Class<?>[] parameterizedTypes = next.getParameterizedTypes();
            //通过方法名称以及对象类型获取Method实例
            Class<?> aClass = object.getClass();
            Method method = aClass.getDeclaredMethod(methodName, parameterizedTypes);
            //获取返回值类型(其实我认为在委托模式下一般不用处理返回值)
            Class<?> returnType = method.getReturnType();
            if (!returnType.getTypeName().equals("void")) {
                //获取返回值
                Object result = method.invoke(object, next.getParams());
                System.out.println("返回值:"+result.toString());
            } else {
                //无返回值方法
                method.invoke(object, next.getParams());
            }
        }
    }

    public static void main(String[] args) {
        //构造主题
        Subject subject = new Subject();

        //构造观察者A和观察者B
        ObserverA observerA = new ObserverA("A");
        ObserverB observerB = new ObserverB();

        //空参方法的委托(将观察者A的getName方法委托给主题执行)
        subject.Attach(observerA,"getName",new Class<?>[]{},new Object[]{});

        //有参方法的委托(将观察者B的returnDouble方法委托给主题执行)
        Class<?>[] classesB= new Class<?>[]{String.class};
        Object[] objectsB = new Object[]{"B"};
        subject.Attach(observerB,"returnDouble",classesB,objectsB);


        try {
            //主题发生改变,调用所有订阅了主题的方法
            subject.NotifyAll();
        } catch (NoSuchMethodException e) {
            System.out.println("没有找到对应方法,请检查参数");
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("访问权限异常,请检查后重试");
            e.printStackTrace();
        }
    }
}
package 事件委托模式;

import java.lang.reflect.ParameterizedType;

public class ObjectMethodAndParameters {

    private final Object object;

    private final String methodName;

    private final Class<?>[] parameterizedTypes;

    private final  Object[] params;

    ObjectMethodAndParameters(Object object,String methodName,Class<?>[] parameterizedTypes,Object[] params) {
        this.object = object;
        this.methodName = methodName;
        this.parameterizedTypes = parameterizedTypes;
        this.params = params;
    }

    public Object getObject() {
        return object;
    }

    public Class<?>[] getParameterizedTypes() {
        return parameterizedTypes;
    }

    public String getMethodName() {
        return methodName;
    }

    public Object[] getParams() {
        return params;
    }

    //刚好的实现是重写HashCode方法
    @Override
    public boolean equals(Object object) {
        //非空判断
        if (object == null) {
            return false;
        }
        //判断类型
        Class<?> aClass = object.getClass();
        if (!(aClass == ObjectMethodAndParameters.class)) {
            return false;
        }
        //判断具体参数
        ObjectMethodAndParameters temp = (ObjectMethodAndParameters) object;
        if (temp.getObject() == this.getObject() && temp.getMethodName().equals(this.getMethodName())
            &&temp.getParameterizedTypes() == this.getParameterizedTypes() && temp.getParams() == this.getParams()) {
            return true;
        }
        return false;
    }
}

 

观察者A类实现:

package 事件委托模式;

public class ObserverA {

    private final String name;

    ObserverA(String name) {
        this.name = name;
    }

    public String getName() {
        System.out.println("委托A执行成功");
        return name;
    }

}

观察者B类实现:

package 事件委托模式;

public class ObserverB {

    public String returnDouble(String name) {
        System.out.println("委托B执行成功");
        return name +name;
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值