【设计模式 03】装饰模式——俄罗斯套娃?
装饰模式(俄罗斯套娃?)
装饰模式:动态的给某些对象添加额外的功能
参考:
简书 | 装饰模式
博客园 | 简说设计模式——装饰模式
博客园 | 装饰器模式 Decorator 结构型 设计模式 (十)
什么是装饰模式
装饰模式也叫装饰器模式,python中的装饰器就是这种模式的体现,对于一个类,如果要添加一个新功能,除了修改代码外(违反开闭原则),可以使用继承,但通过继承添加新功能并不适合所有场景,如
- 类不可见或不允许继承
- 需要对一批类似的兄弟类添加同一个新功能时,继承会产生大量的子类
- 希望新功能的添加和撤销是动态的
- …
装饰模式中的对象包括:
装饰器(用来为被装饰对象动态添加新功能)
抽象被装饰对象(所有能被装饰对象的抽象)
被装饰对象
客户端如果希望给某个对象动态添加一个新功能,就可以把这个对象(被装饰对象)传递给装饰器,由装饰器实现新功能,并保存一个被装饰对象的引用,并返回给客户端一个装饰器对象,这样,被装饰对象原来的行为和属性并没有改变,甚至被装饰对象本身就没有改变,只是在外面套了一个壳子,新功能是这个壳子提供的。就像TCP/IP协议栈中,应用层的数据包到传输层通过加TCP或UDP首部来传输一样。
装饰模式优缺点
优点:
- 一个装饰器可以给多个不同的类动态添加新功能
- 新功能由装饰器实现,不需要修改被装饰对象,有一定的安全性
- 多个装饰器可以配合嵌套使用,以此实现更复杂的功能
- 新功能不影响原来的功能,添加和撤销都方便
缺点:
过多的装饰类可能使程序变得很复杂
装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
作者:慵懒的阳光丶
适用场景
- 要添加的新功能与原有类关联不大时
- 新功能需要方便添加和撤销时
- 不能或不方便通过继承实现新功能时
例
比如卖烤冷面,最基本的就是面(抽象被装饰对象)具体的就是烤冷面(被装饰对象),然后可以往面里面加各种配料(抽象装饰器),如鸡蛋,辣条等(具体装饰器),由于不同配料的加入顺序对最后的烤冷面有影响,所以如果要用继承拓展“烤冷面”,那先加鸡蛋再加辣条和先加辣条再加鸡蛋就需要写两个子类,造成冗余重复,这种场景就适合适用装饰模式。
抽象被装饰对象
package pers.junebao.decorator_pattern;public abstract class Noodles {public String rawMaterial; // 配料public abstract void sayWhoAmI();
}
具体的被装饰对象:
package pers.junebao.decorator_pattern;public class BakedColdNoodles extends Noodles {BakedColdNoodles() {this.rawMaterial = "面"; // 最原始的烤冷面,配料只有面}@Overridepublic void sayWhoAmI() {System.out.println("我是普通烤冷面!");}
}
抽象装饰器:
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public abstract class Burden extends Noodles {public Noodles noodles; // 装饰器中保留一份被装饰对象的引用,方便客户端使用public Burden(Noodles noodles) {this.noodles = noodles;}
}
- 装饰器是为某一类对象提供装饰的(这里就是实现了Noodles 的类)
具体的装饰器类:
加鸡蛋
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddEggs extends Burden {public AddEggs(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + ", 鸡蛋";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了鸡蛋的烤冷面!!");}}
加辣条
package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddSpicyStrips extends Burden{public AddSpicyStrips(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + " ,辣条";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了辣条的烤冷面!!");} }
客户端:
package pers.junebao.decorator_pattern;import pers.junebao.decorator_pattern.decorator.AddEggs;
import pers.junebao.decorator_pattern.decorator.AddSpicyStrips;public class Main {public static void main(String[] args) {Noodles bcn = new BakedColdNoodles();Noodles bcnAddEgg = new AddEggs(bcn);bcnAddEgg.sayWhoAmI();System.out.println(bcnAddEgg.rawMaterial);Noodles bcnEggSpicyS = new AddSpicyStrips(bcnAddEgg);bcnEggSpicyS.sayWhoAmI();System.out.println(bcnEggSpicyS.rawMaterial);}
}
/*
我是加了鸡蛋的烤冷面!!
面, 鸡蛋
我是加了辣条的烤冷面!!
面, 鸡蛋 ,辣条*/
这样如果想先加辣条在家鸡蛋,就可以使用AddSpicyStrips先装饰BakedColdNoodles,再用AddEggs装饰AddSpicyStrips。
GitHub | 完整代码
【设计模式 03】装饰模式——俄罗斯套娃?相关推荐
- 设计模式03:装饰模式
系列总链接:https://blog.csdn.net/qq_22122811/article/details/112360387 参考:https://blog.csdn.net/hnust_xie ...
- 设计模式之装饰模式20170726
结构型设计模式之装饰模式: 一.含义 动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活. 通俗来讲,装饰模式是对类的功能进行加强或减弱. 二.代码说明 1.主要有两个角 ...
- java设计模式之装饰模式_Java中的装饰器设计模式
java设计模式之装饰模式 装饰器设计模式允许在运行时将附加职责或行为动态附加到对象. 它是一种结构模式,利用聚合来组合这些行为. 在本教程中,我们将学习实现装饰器模式. UML图: 让我们从装饰器模 ...
- 设计模式03 - 装饰者模式
引入: 曾今以为继承能解决一切问题.在程序运行时发现,扩展的威力远大于编译时扩展的威力. 装饰者模式: 好处: 一旦知道装饰的技巧,你将能给你的(或别人的)对象一个新的责任,而不需要对底层class的 ...
- 大话设计模式之装饰模式(python实现)
大话设计模式之装饰模式 使用场景 定义 装饰模式结构图 python实现装饰模式 代码结构图 优点 使用场景 建造过程不稳定,不确定.把所需的功能按照正确的顺序串联起来进行控制. 新加入的东西仅仅是为 ...
- 设计模式之装饰模式详解(附应用举例实现)
文章目录 1 装饰模式介绍 2 装饰模式详解 2.1 装饰模式结构 2.2 装饰模式实现 2.3 装饰模式应用举例 3 透明装饰模式和半透明装饰模式 1 装饰模式介绍 在生活中,我们往往会给图片增加一 ...
- 设计模式之 装饰模式
设计模式之 装饰模式 概述: 装饰模式(Decorator Pattern) 又叫装饰者模式:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也 ...
- 设计模式之三 装饰模式
1.场景模拟 这样让想起了老李,我跟老李是很要好的哥们,当然他不像我还是光棍,所以他不光有友情还有爱情了,不过,就在最近几天他们吵架啦,什么原因?就不多说啦,总之身为男人的老李还是决定主动认错挽回女方 ...
- 设计模式之装饰模式(Decorator)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
最新文章
- 上传图片时出现Request 对象 错误 'ASP 0104 80004005'
- 转载 开发人员一定要加入收藏夹的网站
- 转: Linux下使用java -jar运行可执行jar包的正确方式
- .NET Compact Framework s60v3(在S60上运行Windows Mobile程序)
- boost::mp11::mp_assign相关用法的测试程序
- 算法题解:动态规划解0-1背包问题
- 【算法学习笔记】85.破环为链 序列DP 松弛+代价 SJTU OJ 1073 能量项链
- [转载]如何决定要使用多少点来做FFT?(转载)
- PHP MySQL 相关函数(上)
- oracle sqlplus ed,Uedit32与SQLPlus结合使用技巧-数据库专栏,ORACLE
- java中什么是线程安全_Java 多线程:什么是线程安全性
- jenkins + maven + nexus + [ svn 或 GitLab 或 GitHub ]
- 如何用公式编辑器打长等号
- 【Vue】postman汉化教程 保姆级教程 包教会
- blink usb无线网卡驱动 linux,lblink无线网卡驱动下载官方版_blink无线网卡驱动_blink无线网卡驱动_东坡下载...
- can总线一帧多少字节多少位_汽车CAN总线数据帧解析---汽车语言知多少
- 使用MATLAB Mapping工具箱创建和编辑地图
- 统计学考研笔记:季度指数
- 1038 Recover the Smallest Number (30 分)-字符串分段排序
- UI设计师未来职业规划
热门文章
- [基础篇]ESP32-RTOS-SDK教程(一)之Windows环境搭建
- [LeedCode]921. 使括号有效的最少添加
- C# 使用Conditional特性而不是#if条件编译
- 对session的理解
- PHP内核探索之变量(6)- 后续内核探索系列大纲备忘
- php CI 实战教程:如何去掉index.php目录
- 用c#写的一个局域网聊天客户端 类似小飞鸽
- 神马是线程?PHP对其具体的应用?应用在哪里?
- 遇到问题了 .net项目发布到iis6,没有权限访问!?
- 数据结构排序法之插入法