【设计模式】深入解析代理模式(委托模式):代理模式思想、静态模式和动态模式定义与区别、静态代理模式代码实现


代理模式


代理模式,也叫委托模式

Spring AOP 是基于动态代理来实现 AOP 的


定义


  • 其他对象提供一种代理 以控制对这个对象的访问
  • 它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端目标对象之间起到中介的作用。


使用代理前:


使用代理后:


代理模式角色


角色名称 描述 房屋租赁中的对应角色
Subject 业务接口类: 可以是抽象类或者接口(不一定有)。 定义了业务操作的接口。 房屋租赁的通用操作(如出租房屋)
RealSubject 业务实现类: 具体的业务执行,也就是被代理对象 房东
Proxy 代理类RealSubject 的代理代理对象内部含有对 RealSubject 的引用,并实现 Subject 接口 中介

UML 类图如下:

简单总结一下:

  • 首先,Subject 是一个接口或者抽象类,定义了 RealSubjectProxy共同方法
  • RealSubject 实际执行任务的对象,而 Proxy控制对 RealSubject 的访问

两种代理模式的区别


代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加增强


根据代理创建时期代理模式分为静态代理动态代理静态代理是在编译时确定代理关系,而动态代理是在运行时动态生成的


  • 静态代理:
    • 由程序员创建代理类特定工具自动生成源代码再对其编译
    • 程序运行前代理类 .class 文件就已经存在了。

  • 动态代理:
    • 在程序运行时,运用反射机制动态创建而成。

静态代理


静态代理:在程序运行前,代理类的 .class 文件就已经存在了。

在出租房子之前,中介已经做好了相关的工作,就等租户来租房子了;

我们通过代码来加深理解。以房租租赁为例:


定义接口(定义房东要做的事情,也是中介需要做的事情):


实现接口(房东出租房子):


代理(中介,帮房东出租房子):


  1. RealSubject 实际执行任务的对象,而 Proxy控制对 RealSubject 的访问
  2. 代理对象内部含有对 RealSubject 的引用,并实现 Subject 接口

所以中介类中,应该有房东,因为只有房东授权,中介才能带中介看房子


中介的 saleHouse() 调用房东的 saleHouse(),表示真正卖房的人是房东:

本质是房东的 saleHouse() 借助中介的 saleHouse() 套了一层壳:


租客来看房了,房租对中介进行授权,让中介有带租客看房子的权力:


我们在拆的细一点:


上面的代码逻辑是,房东需要出租一个房子 target 给租客,房东先把房子 target 这个任务给中介;


但是上面的代码还是不够好,因为租房子应该使用接口的方法:


修改:



运行结果:



租客 中介(Proxy) 房东(RealSubject) 我要租房 检查租客资质 转发租房请求 确认可出租 签订代理合同 交付钥匙 租客 中介(Proxy) 房东(RealSubject)


上面这个代理实现方式就是静态代理(仿佛啥也没干)

从上述程序可以看出,虽然静态代理完成了对目标对象的代理,但是由于代码都写死了对目标对象的每个方法的增强都是手动完成的,非常不灵活。所以日常开发几乎看不到静态代理的场景。


接下来新增需求:中介又新增了其他业务:代理房屋出售。

我们需要对上述代码进行修改:


  1. 接口定义修改。

  1. 接口实现修改。

  1. 代理类修改。

从上述代码可以看出,我们修改接口(Subject)业务实现类(RealSubject)时,还需要修改代理(Proxy)

同样的,如果有新增接口(Subject)业务实现类(RealSubject),也需要对每一个业务实现类新增代理类(Proxy)

既然代理的流程是一样的,有没有一种办法,让他们通过一个代理类来实现呢? 这就需要用到动态代理技术了。


动态代理


相比于静态代理来说,动态代理更加灵活

我们不需要针对每个目标对象单独创建一个代理对象,而是把这个创建代理对象的工作推迟到程序运行时由 JVM 来实现。也就是说动态代理在程序运行时,根据需要动态创建生成。

比如房屋中介,我不需要提前预测都有哪些业务,而是业务来了我再根据情况创建。


Java 也对动态代理进行了实现,并给我们提供了一些 API,常见的实现方式有两种:

  1. JDK 动态代理。
  2. CGLIB 动态代理。

动态代理在我们日常开发中使用的相对较少,但是在框架中几乎是必用的一门技术。

学会了动态代理之后,对于我们理解和学习各种框架的原理也非常有帮助:

https://xiaolllei.blog.csdn.net/article/details/147427226?spm=1011.2415.3001.5331


相关推荐
元亓亓亓21 分钟前
Java后端开发day36--源码解析:HashMap
java·开发语言·数据结构
sd213151225 分钟前
RabbitMQ 复习总结
java·rabbitmq
他҈姓҈林҈1 小时前
使用 Spring Boot 进行开发
spring boot
码银3 小时前
Java 集合:泛型、Set 集合及其实现类详解
java·开发语言
东阳马生架构3 小时前
Nacos简介—4.Nacos架构和原理
java
柏油3 小时前
MySQL InnoDB 行锁
数据库·后端·mysql
咖啡调调。3 小时前
使用Django框架表单
后端·python·django
Java&Develop3 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk3 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务
摆烂工程师3 小时前
全网最详细的5分钟快速申请一个国际 “edu教育邮箱” 的保姆级教程!
前端·后端·程序员