Android开发程序员Android开发

【设计模式笔记】(十六)- 代理模式

2018-06-24  本文已影响82人  MrTrying

一、简述

代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。

其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中的中介者对象也是代理模式的应用,其他的对象的交互都是交给了中介者对象处理的。而在生活中就更多类似代理模式的例子,例如:抢票插件、科学上网等等。

代理模式
/**抽象主题*/
public interface Subject {
    public void visit();
}

/**被代理主题*/
public class RealSubject implements Subject {
    @Override
    public void visit() {
        System.out.print("this is real subject");
    }
}

/**代理主题*/
public class ProxySubject implements Subject {
    //真实主题
    private Subject realSubject;

    public ProxySubject(@NotNull Subject subject){
        realSubject = subject;
    }

    @Override
    public void visit() {
        System.out.print("proxy start");
        realSubject.visit();
        System.out.print("proxy end");
    }
}

/**客户类*/
public class Client {
    public static void main(String[] args){
        //创建被代理对象
        RealSubject realSubject = new RealSubject();
        //创建代理对象
        ProxySubject proxySubject = new ProxySubject(realSubject);
        //调用方法
        proxySubject.visit();
    }
}

输出结果:
proxy start
this is real subject
proxy end

二、动态代理

上一部分中所讲述的,其实是静态代理,也就是在代码的编译阶段生成代理类来完成代理对象的一系列操作。而动态代理则是在运行时动态生成代理类对象。代理对象的生成是利用JDKjava.lang.reflect.Proxy类,使用newProxyInstance方法可以创建一个我们所需要的代理对象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
//代码省略...
}

newProxyInstance方法是Proxy的一个静态方法,并且接收三个参数

其中InvocationHandlerinvoke方法如下:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;`

  • Object proxy:执行方法的代理对象
  • Method method:被执行的方法的对象
  • Object[] args:被执行的方法的参数
    返回值则是代理对象调用方法时所返回的值

依然使用Subject作为例子,看看简单的代码实现(代码没有封装)

//创建被代理对象
Subject realSubject = new RealSubject();
//创建代理对象
Subject subject = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
    new Class[]{Subject.class},
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(realSubject, args);
        }
    });
subject.visit();

从代码上来看,比之前的静态代理要简单很多,没有那么多的类和对象;但是相对的在代码性能上有所牺牲,而且对于不太熟悉反射相关的知识的开发者并不是太友好。

通过反射类ProxyInvocationHandler回调接口实现的JDK动态代理,要求被代理类必须实现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方方式实现动态代理。

三、其他代理分类

静态代理和动态代理是代码方面来区分的代理模式,也可以从适用范围来区分不同类型的代理实现

这里要注意的是,静态和动态代理都可以应用于上述4种情形,两者是各自独立的变化。

四、总结

代理模式使用非常广泛,基本在其他的设计模式中也能看到代理模式的影子,但是使用时针对性较强,而且模式本身并没有什么突出的优缺点,基本上可以放心使用

PS:从此你写过的代码都像代理模式

「推荐」设计模式系列

设计模式(零)- 面向对象的六大原则
设计模式(一)- 单例模式
设计模式(二)- Builder模式
设计模式(三)- 原型模式
设计模式(四)- 工厂模式
设计模式(五)- 策略模式
设计模式(六)- 状态模式
设计模式(七)- 责任链模式
设计模式(八)- 解释器模式
设计模式(九)- 命令模式
设计模式(十)- 观察者模式
设计模式(十一)- 备忘录模式
设计模式(十二)- 迭代器模式
设计模式(十三)- 模板方法模式
设计模式(十四)- 访问者模式
设计模式(十五)- 中介者模式
设计模式(十六)- 代理模式
设计模式(十七)- 组合模式
【设计模式笔记】(十八)- 适配器模式
【设计模式笔记】(十九)- 装饰者模式

上一篇 下一篇

猜你喜欢

热点阅读