【设计模式】深入解析代理模式(委托模式):代理模式思想、静态模式和动态模式定义与区别、静态代理模式代码实现
代理模式
代理模式
,也叫委托模式
。
Spring AOP 是基于动态代理来实现 AOP 的
定义
- 为
其他对象
提供一种代理
以控制对这个对象的访问
。 - 它的作用就是
通过提供一个代理类
,让我们在调用目标方法
的时候,不再是直接对目标方法进行调用
,而是通过代理类间接调用
。
在某些情况下,一个对象不适合或者不能直接引用另一个对象
,而代理对象
可以在客户端
和目标对象
之间起到中介
的作用。
使用代理前:
使用代理后:
代理模式角色
角色名称 | 描述 | 房屋租赁中的对应角色 |
---|---|---|
Subject | 业务接口类 :可以是抽象类或者接口(不一定有)。 定义了业务操作的接口。 | 房屋租赁的通用操作(如出租房屋) |
RealSubject | 业务实现类 :具体的业务执行,也就是 被代理对象 。 | 房东 |
Proxy | 代理类 :RealSubject 的代理 。代理对象内部含有对 RealSubject 的引用,并实现 Subject 接口 。 | 中介 |
UML 类图如下:
简单总结一下:
- 首先,
Subject
是一个接口
或者抽象类
,定义了RealSubject
和Proxy
的共同方法
。 RealSubject
是实际执行任务
的对象,而Proxy
则控制对 RealSubject 的访问
。
两种代理模式的区别
代理模式
可以在不修改被代理对象的基础上
,通过扩展代理类
,进行一些功能的附加
与增强
。
根据代理
的创建时期
,代理模式
分为静态代理
和动态代理
,静态代理
是在编译时
就确定代理关系
,而动态代理
是在运行时动态生成的
。
- 静态代理:
- 由程序员
创建代理类
或特定工具
自动生成源代码
再对其编译
; - 在
程序运行前
,代理类
的.class 文件
就已经存在了。
- 由程序员
- 动态代理:
- 在程序运行时,运用
反射机制
,动态创建
而成。
- 在程序运行时,运用
静态代理
静态代理:在程序运行前,代理类的 .class 文件就已经存在了。
在出租房子之前,中介已经做好了相关的工作,就等租户来租房子了;
我们通过代码来加深理解。以房租租赁为例:
定义接口(定义房东要做的事情,也是中介需要做的事情):
实现接口(房东出租房子):
代理(中介,帮房东出租房子):
RealSubject
是实际执行任务
的对象,而Proxy
则控制对 RealSubject 的访问
;代理对象内部含有对 RealSubject 的引用,并实现 Subject 接口
;
所以中介类中,应该有房东,因为只有房东授权,中介才能带中介看房子
:
中介的 saleHouse()
调用房东的 saleHouse()
,表示真正卖房的人是房东:
本质是房东的 saleHouse() 借助中介的 saleHouse() 套了一层壳:
租客来看房了,房租对中介进行授权,让中介有带租客看房子的权力:
我们在拆的细一点:
上面的代码逻辑是,房东需要出租一个房子 target 给租客,房东先把房子 target 这个任务给中介;
但是上面的代码还是不够好,因为租房子应该使用接口的方法:
修改:
运行结果:
上面这个代理实现方式就是静态代理(仿佛啥也没干)
。
从上述程序可以看出,虽然静态代理
也完成了对目标对象的代理
,但是由于代码都写死了
,对目标对象的每个方法的增强都是手动完成的,非常不灵活
。所以日常开发几乎看不到静态代理的场景。
接下来新增需求:中介又新增了其他业务:代理房屋出售。
我们需要对上述代码进行修改:
- 接口定义修改。
- 接口实现修改。
- 代理类修改。
从上述代码可以看出,我们修改接口(Subject)
和业务实现类(RealSubject)
时,还需要修改代理(Proxy)
。
同样的,如果有新增接口(Subject)
和业务实现类(RealSubject)
,也需要对每一个业务实现类新增代理类(Proxy)
。
既然代理的流程是一样的,有没有一种办法,让他们通过一个代理类来实现呢? 这就需要用到动态代理技术了。
动态代理
相比于静态代理来说,动态代理更加灵活
。
我们不需要针对每个目标对象
都单独创建一个代理对象
,而是把这个创建代理对象
的工作推迟到程序运行时由 JVM 来实现
。也就是说动态代理在程序运行时,根据需要动态创建生成。
比如房屋中介,我不需要提前预测都有哪些业务,而是业务来了我再根据情况创建。
Java 也对动态代理进行了实现,并给我们提供了一些 API,常见的实现方式有两种:
- JDK 动态代理。
- CGLIB 动态代理。
动态代理在我们日常开发中使用的相对较少,但是在框架中几乎是必用的一门技术。
学会了动态代理之后,对于我们理解和学习各种框架的原理也非常有帮助:
https://xiaolllei.blog.csdn.net/article/details/147427226?spm=1011.2415.3001.5331