设计模式--代理模式(静态代理和动态代理)

代理模式

  1. 需要的是代理者,被代理者,共性接口,测试类

  2. 比如A访问C。B有一个代理C,B把内容交代后,给了C,C作为代理,需要对A进行一些其他访问控制,判断,同时C也完整的执行了B的内容。因此A对C的访问实际上就是A间接的访问B

  3. 静态代理和动态代理

  4. 反射的应用:动态代理

  5. 在不改变接口的前提下,控制对象的访问

  6. 从封装的角度讲, 是为了解决类与类之间相互调用而由此导致的耦合关系

  7. 从复用角度讲,可以解决不同类调用一个复杂类时,仅仅因较小的改变而导致整个复杂类新建一个类,a-c1,b-c2

  8. 强调类之间的封装和某方面的复用

代理 Boss和秘书(静态代理)
Interface Person{
  void speak();
}
//被代理者
class Boss implements person{
  @Override
   public void speak() {
       System.out.println("Boss:今晚开会");
   }
}
//代理者  中间人
class Agent implements Person{
    private Boss boss;

    public Agent(Boss boss){
        this.boss = boss;
    }

    public static void agentSpeak(){
        System.out.println("秘书:今晚开会");
    }
    @Override
    public void speak() {
        agentSpeak();
        boss.speak();//boss对象调用自己的方法,这个speak是调用Boss的实现方法
    }
}
//测试类
public class ProxyModel {
    public static void main(String[] args) {
        Agent agent = new Agent(new Boss());
        agent.speak();//秘书说的话就是Boss说的话
    }
}

动态代理(反射)
public class DynamicProxyMode {
    public static void main(String[] args) {
        Boss boss = new Boss();//来了一个需要被代理对象
        Person proxyInstance = (Person) ProxyFactory.getProxyInstance(boss);//通过代理工厂,传入对象得到一个代理实例,是接口类型的
        /**
         * 当代理类的对象调用speak()时,会自动的调用invoke().
         * 因为在代理工厂里,创建了MyInvocationHandler的bind方法,来和传进来的被代理类连接
         * obj传到创建了MyInvocationHandler的bind()中,然后把这个MyInvocationHandler的对象传给proxy()
         * proxy中最后一个参数类型就是InvocationHandler,而且InvocationHandler的invoke有返回值,因此返回了掉用的结果
         * 因此间接的实现了代理对象调用方法
         */
//        接口类型的代理实例.被代理类的方法
        /**
         * 经过上面的创建代理过程后,该接口类型的代理对象已经可以调用继承了接口的代理类的方法了
         */
        /**
         * 调用speak()
         */
        proxyInstance.speak();//代理实例去代理的输出被代理类的方法
        proxyInstance.eat();
    }
}
interface Person{
    void speak();
    void eat();
}
class Boss implements Person{
    @Override
    public void speak() {
        System.out.println("今晚开会");
    }

    @Override
    public void eat() {
        System.out.println("我在吃");
    }
}
/*
动态代理时需要解决的问题
   - 1. 如何根据加载到内存中的被代理类,动态的创建一个代理类及对象
   - 2. 当通过代理类中的对象调用方法时,如何动态的去调用被代理类中的同名方法
 */
//创建一个代理工厂,专门产生代理类
class ProxyFactory {
    /**
     * 调用此方法,获取代理一个代理对象,解决问题一
     * @param obj 被代理类的对象
     * @return 代理实例
     */
    public static Object getProxyInstance(Object obj){//obj是被代理类的对象

        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);//作用:联系MyInvocationHandler类,去实现具体的代理过程
        /**
         * static Object newProxyInstance(ClassLoader loader, 类<?>[] interfaces, InvocationHandler h)
         * 参数
         * loader - 类加载器来定义代理类
         * interfaces - 代理类实现的接口列表
         * h - 调度方法调用的调用处理函数
         */
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }
}
//创建一个InvocationHandler的实现类,InvocationHandler是由代理实例的调用处理程序实现的接口
class MyInvocationHandler implements InvocationHandler {
    private Object obj;//需要使用被代理类的对象赋值

    /**
     * 绑定被代理对象
     * @param obj
     */
    public void bind(Object obj){
        this.obj = obj;
    }

    //重写InvocationHandler接口的invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * Method相当于是超级类,它的对象调用Method的invoke
         */
        Object returnValue = method.invoke(obj, args); //超级类,也就是相当于Object一样的超级东西,调用Methods的invoke方法
        return returnValue;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值