装饰器模式和代理模式的区别
从 UML 类图和实现代码上看,代理模式与装饰器模式几乎一模一样。代理模式的 Subject 对应装饰器模式的 Component,代理模式的 RealSubject 对应装饰器模式的 Concrete Component,代理模式的 Proxy 对应装饰器模式的 Decorator。
确实,从实现代码的角度看,代理模式的确与装饰器模式是一样的(其实装饰器模式就是代理模式的一个特殊应用),但是这两种设计模式所面向的功能扩展面是不一样的。
装饰器模式强调自身功能的扩展。Decorator 所做的就是增强 Concrete Component 的功能(也有可能减弱功能),主体对象为 Concrete Component,着重类功能的变化。
代理模式强调对代理过程的控制。Proxy 完全掌握对 RealSubject 的访问控制,因此,Proxy 可以决定对 RealSubject 进行功能扩展、功能缩减甚至功能散失(不调用 RealSubject 方法),主体对象为 Proxy。
假设现在小明想租房,那么肯定需要搜索房源、联系房东谈价格等事情。
新建房屋中介(代理)类。
修改 HouseAgent(抽象装饰角色)类,代码如下:
由以上实例可以总结出:
对于代理类,如何调用对象的某一功能是思考重点,不需要兼顾对象的所有功能;对于装饰类,如何扩展对象的某一功能是思考重点,同时也需要兼顾对象的其它功能,因为再怎么装饰,本质也是对象本身,要担负起对象应有的职责。由于被装饰者的职责一旦增加,装饰类也需要有相应的扩展,所以必然会造成编码的负担,增加程序的复杂性。
设计模式就是为了提升代码的可扩展性,灵活应用即可,没有必要生搬硬套,非要分出个所以然来,装饰器模式和代理模式的区别也是如此。
确实,从实现代码的角度看,代理模式的确与装饰器模式是一样的(其实装饰器模式就是代理模式的一个特殊应用),但是这两种设计模式所面向的功能扩展面是不一样的。
装饰器模式强调自身功能的扩展。Decorator 所做的就是增强 Concrete Component 的功能(也有可能减弱功能),主体对象为 Concrete Component,着重类功能的变化。
代理模式强调对代理过程的控制。Proxy 完全掌握对 RealSubject 的访问控制,因此,Proxy 可以决定对 RealSubject 进行功能扩展、功能缩减甚至功能散失(不调用 RealSubject 方法),主体对象为 Proxy。
实例说明
下面通过举例,针对两者的区别进行探讨。假设现在小明想租房,那么肯定需要搜索房源、联系房东谈价格等事情。
1. 基础实现
首先定义一个租房的接口,代码如下:public interface RentHouse { void renting(); }创建人(小明)类实现租房接口。
public class People implements RentHouse { @Override public void renting() { System.out.println("小明租房"); } }
2. 代理模式
按照代理模式进行思考,小明只需要找到一个房产中介,让中介去做房源搜索、联系房东这些事情,小明只需等待通知就可以了。新建房屋中介(代理)类。
public class HouseAgent implements RentHouse{ private People people; public HouseAgent(People people){ this.people=people; } @Override public void renting() { System.out.println("房产中介搜索房源"); people.renting(); System.out.println("房产中介联系房东"); } }测试类如下:
public static void main(String[] args) { // 代理模式 People people = new People(); RentHouse rentHouse = new HouseAgent(people); rentHouse.renting(); }运行结果如下:
房产中介搜索房源
小明租房
房产中介联系房东
3. 装饰器模式
如果采用装饰器模式进行思考,因为装饰器模式强调的是自身功能扩展,也就是说,如果要租房子,小明自身就要增加搜索房源、联系房东能力扩展。通过相应的装饰器,提升自身能力,一个人做完所有的事情。修改 HouseAgent(抽象装饰角色)类,代码如下:
public class HouseAgent implements RentHouse { private People people; public HouseAgent(People people) { this.people = people; } @Override public void renting() { //System.out.println("房产中介搜索房源"); people.renting(); //System.out.println("房产中介联系房东"); } }新建 PowerfulXiaoMing(具体装饰角色)类,代码如下:
public class PowerfulXiaoMing extends HouseAgent { public PowerfulXiaoMing(People people) { super(people); } @Override public void renting() { super.renting(); addSkill(); } public void addSkill() { System.out.println("搜索房源"); System.out.println("联系房东"); } }测试类代码如下:
public static void main(String[] args) { // 装饰器模式 People people = new People(); HouseAgent rh = new PowerfulXiaoMing(people); rh.renting(); }运行结果如下:
小明租房
搜索房源
联系房东
由以上实例可以总结出:
- 代理模式注重对对象某一功能的流程把控和辅助。它可以控制对象做某些事,重心是为了借用对象的功能完成某一流程,而非对象功能如何。
- 装饰模式注重对对象功能的扩展,它不关心外界如何调用,只注重对对象功能的加强,装饰后还是对象本身。
对于代理类,如何调用对象的某一功能是思考重点,不需要兼顾对象的所有功能;对于装饰类,如何扩展对象的某一功能是思考重点,同时也需要兼顾对象的其它功能,因为再怎么装饰,本质也是对象本身,要担负起对象应有的职责。由于被装饰者的职责一旦增加,装饰类也需要有相应的扩展,所以必然会造成编码的负担,增加程序的复杂性。
设计模式就是为了提升代码的可扩展性,灵活应用即可,没有必要生搬硬套,非要分出个所以然来,装饰器模式和代理模式的区别也是如此。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算