代理模式
为其它对象提供一种代理以控制这个对象的访问。
简单的举个例子,可以看作一个玩家自己不打游戏,而是通过找代练让代练去操作游戏。诸如Windows上的快捷方式,其实都是一种代理模式。
优缺点
优点
- 职责清晰。真实的角色就是实现实际的业务逻辑,不用担心其他非本职责的事务。
- 高扩展性。代理类完全可以在不做任何修改的情况下使用。
- 智能化。比如动态代理。
缺点
- 有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
结构图
代理模式中有以下角色:
- 抽象主题类(Subject): 声明真实主题和代理Proxy 的共同接口方法。
- 真实主题类(RealSubject): 具体主题角色,定义了 Proxy 所代表的真实实体
- 代理类(Proxy):持有对真实主题类的引用,使代理可以访问实体,并提供一个与 Subject 的接口相同的接口。
- 客户端类。
代码示例
首先我们来看一下对应基本结构下的代理模式。
Subject抽象类
定义了 RealSubject 和 Proxy 的共同接口,这样就在任何使用 RealSubject 的地方都可以使用Proxy。
1 | public abstract class Subject { |
RealSubject类
1 | public class RealSubject extends Subject { |
Proxy类
代理类。一个代理类可以代理多个被委托者或被代理者,因此一个代理类具体代理哪个真实主题角色,是由场景类决定的。
1 | public class Proxy extends Subject { |
Client 客户端
1 | public class Client { |
静态代理
所谓静态代理类是指:由程序员创建或由特定工具自动生成源代码,再对其进行编译。在程序运行之前,代理类的.class文件就已经存在了。
抽象主题类
1 | public interface IShop { |
真实主题类
1 | public class Allenmistake implements IShop { |
代理类
1 | public class Purchasing implements IShop { |
4、客户端类
1 | public class Clent { |
动态代理
在代码运行时通过反射来动态地生成代理类的对象,并确定到底来代理谁。
通过动态代理,我们不再需要手动创建代理类,只需编写一个动态处理器即可,而真正的代理对象由JDK在运行时帮我们创建。所以我们也将之称为JDK动态代理。
方法步骤如下:(重点)
写一个代理类实现 InvocationHandler
接口,通过构造函数把代理对象(具体目标类)传入到此处理器中,在invoke()
方法中增加method.invoke(realSubject, args)
。在调用方法时,通过java.lang.reflect.Proxy
和newProxyInstance()
来获取代理实现类,生成代理对象时,直接调用方法即可。真实主题类发生变化时,由于它实现了公用的接口,因此代理类不需要修改。
改写静态代理的代理类和客户端类,如下所示:
动态代理类
1 | public class DynamicPurchasing implements InvocationHandler { |
客户端类
1 | public class Clent { |