三分钟理解“装饰模式”——设计模式轻松掌握
什么是装饰模式?
在运行的过程中,给一个对象动态地添加一些额外的行为。每一个具体的装饰类都为被装饰类添加一个功能。
装饰模式的类图
1.需要被装饰的对象所在的类和装饰类都有一个共同的父类Component,该类中拥有需要添加额外功能的函数:operation();
class ConcreteComponent() extends Component{
public void operation(){
//本函数原本就要做的事情
}
}
2.ConcreteComponent是需要被装饰的类;Decorator是装饰类。
3.Decorator类中持有被装饰对象的引用,客户端通过setComponent(Component)设置;
4.Decorator类的operation()函数中,执行了被用户set进去的component对象中的operation()函数,也就是首先执行被装饰类原本的功能;
class Decorator() extends Component{//需要被装饰的对象private Component component;//提供给客户端将需要被装饰的对象设置进来public void setComponent(Component component){this.component = component;}//执行需要被装饰对象原本的operation函数public void operation(){this.component.operation();}}
Decorator的子类们的operation()函数,拥有被装饰类原本的功能和新需要增加的功能。
class ConcreteDecorator() extends Decorator{
//需要被装饰的对象
private Component component;
//提供给客户端将需要被装饰的对象设置进来
public void setComponent(Component component){
this.component = component;
}
//执行需要被装饰对象原本的operation函数+附加的功能
public void operation(){
//新的功能……………………
super.operation();
//新的功能……………………
}
}
客户端代码:
public static void main(String[] args) {
//创建一个需要被装饰的对象
ConcreteComponent concreteComponent = new ConcreteComponent();
//创建一系列修饰类的对象
Decorator decoratorA = new ConcreteDecoratorA();
Decorator decoratorB = new ConcreteDecoratorB();
//先使用ConcreteDecoratorA包装被装饰对象
decoratorA.setComponent(concreteComponent);
//再使用ConcreteDecoratorB包装decoratorA对象
decoratorB.setComponent(decoratorA);
}
此时,decoratorB对象就是原本需要被装饰的concreteComponent对象,只不过这个对象的operation()函数在原本operation()的基础上增加了ConcreteDecoratorA和ConcreteDecoratorB新的功能。
装饰模式和建造者模式的异同?
相同点:建造者模式和装饰模式都使用了面向切面编程的思想,装饰模式中的装饰类和建造者模式中建造者类的一个个函数都是为被装饰对象附加函数额外功能或为对象中的属性赋值。
不同点:建造者给对象添砖加瓦的顺序是固定的,在Director类中写好的;
而装饰模式中需要添加哪些操作是由客户端决定的。
建造者模式的详细介绍请移步至:http://blog.csdn.net/u010425776/article/details/48104143
装饰模式的优点
装饰模式是为已有的功能动态添加更多功能的一种方式。
以往在设计程序的过程中,当系统需要新功能时,就在旧的类中添加新的代码。
但这种方式的问题在于,如果它们在类中添加了新的方法、新的字段、新的逻辑,就会增加主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才回执行的特殊行为的需要。
而装饰模式提供了一种非常好的解决方案,
它把每一个要额外添加的功能单独封装在一个个类中,并让这个类包装它所要装饰的对象。
因此,当一个类需要执行特殊行为时,客户端就可以在运行时有选择地添加所需要的附加功能。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Centos7-Firewall防火墙基础讲解
- 优酷iOS插件化页面架构方法
- 处理一次k8s、calico无法分配podIP的心路历程
- 小视频源码,按返回键两次退出
- iOS音视频接入 - TRTC多人音视频通话
- Android平台RTMP推流或轻量级RTSP服务(同屏或摄像头)编码前数据接入类型总结
- 接口测试框架实战(二) | 搞定多环境下的接口测试
- MySQL 案例:“丢失数据”的谜题
- 接口测试框架实战(三) | APIObject 模式、原则与应用
- 接口测试框架实战(四) | 通用 API 封装实战
- 面试字节两轮后被完虐,一份字节跳动面试官给你的Android技术面试指南,请查收!
- 3分钟短文:说说Laravel模型中还算常用的2个“关系”
- iOS音视频接入 - TRTC实时屏幕分享
- 如何维护爬虫代理
- LoRaWAN 帧计数机制及典型问题分析