设计模式11之装饰模式
背景我们在开发过程中 , 如果我们想使用存在的轮子 , 但是轮子的有些功能不能满足我们 。 我们需要对轮子新增想要的功能 。 好的设计方式是不改变轮子的结构 , 动态的扩展功能 。 装饰模式就是这样的一种设计方式 。
什么是装饰模式“
装饰模式(Decorator Pattern)是一种比较常见的模式 , 其定义如下:Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责 。 就增加功能来说 , 装饰模式相比生成子类更为灵活 。 )
”
是不是觉得跟代理模式有些像呢?对代理模式感兴趣的可以看看我的这篇文章:
设计模式6之代理模式
面试必问的动态代理 , 我们来看看它们的源码
别急 , 我们继续往下看 。
装饰模式的主要组成要素为:
“抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象 。 具体构件(ConcreteComponent)角色:实现抽象构件 , 通过装饰角色为其添加一些职责 。 抽象装饰(Decorator)角色:继承抽象构件 , 并包含具体构件的实例 , 可以通过其子类扩展具体构件的功能 。 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法 , 并给具体构件对象添加附加的责任 。 ”
要素之间的关系如下:
文章插图
装饰模式
示例代码Componentpublic interface Component {void operation();}
ConcreteComponentpublic class ConcreteComponent implements Component {public ConcreteComponent() {System.out.println("创建具体构件角色");}@Overridepublic void operation() {System.out.println("调用具体构件角色的方法operation()");}}
Decoratorpublic class Decorator implements Component {private Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}}
ConcreteDecoratorpublic class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedFunction();}public void addedFunction() {System.out.println("为具体构件角色增加额外的功能addedFunction()");}}
测试代码如下:
public class DecoratorTest {public static void main(String[] args){Component p = new ConcreteComponent();p.operation();System.out.println("------------------");Component concreteDecorator = new ConcreteDecorator(p);concreteDecorator.operation();}}
如上代码 , 我们想使用具体构件(即文章开头的轮子)的operation() , 并且想对operation()方法增加一些功能 , 我们构建了一个装饰对象 , 这个对象包裹这具体构件 , 最后我们调用了ConcreteDecorator#operation() , 这个方法就是增强后的方法 。
测试结果:
-------------------调用具体构件角色的方法operation()------------------调用具体构件角色的方法operation()为具体构件角色增加额外的功能addedFunction()
我们对operation()方法增加了功能:
为具体构件角色增加额外的功能addedFunction()
关于装饰模式的思考如果我们需要对当前类添加额外的职责 , 但是又不能通过生成当前类的子类去扩充时 , 就可以使用装饰模式了 。
装饰者模式的优势在于可以动态扩展新功能 , 也可以动态撤销新功能 , 还可以将多组功能排列组合生成新功能 。
其实Java中的InputStream的子类 FilterInputStream , OutputStream 的子类 FilterOutputStream 等 , 它们都是抽象装饰类 。
BufferedReader in=new BufferedReader(new FileReader("lvshen_av.txt));String s=in.readLine();
如上代码就使用了装饰模式 。
对于构件Component和装饰者Decorator来说 , 它们之间不相互耦合 。 装饰者是从外部扩展构件的功能 , 不需要知道构件的具体结构 , 不需要改变构件 。
通俗点就是:
史塔克穿上钢铁侠战甲就变成钢铁侠 , 同样他的女友小辣椒也能穿上钢铁侠战甲变成钢铁侠 。 钢铁侠战甲不关注谁穿上了它 。 不同的人穿上就成了不同的钢铁侠 。
但是只要注意不要多层装饰 , 这样会显得系统很复杂 。
例如 , 史塔克穿上钢铁侠战甲成为钢铁侠 , 钢铁侠穿上反浩克战甲 。 虽然力量变强了 , 但是操作难度也变高了 。
关于装饰模式与代理模式两者都是对功能增强 。 面试会经常问这两点区别 。
我认为 , 装饰器模式关注于在一个对象上动态的添加方法 , 代理模式关注于控制对象的访问 。 换句话 说 , 用代理模式 , 代理类(proxy class)可以对它的客户隐藏一个对象的具体信息 。 因此 , 当使用代理模式的时候 , 我们常常在一个代理类中创建一个对象的实例 。 当我们使用装饰器模式的时候 , 我们通常的做法是将原始对象作为一个参数传给装饰者的构造器 。
- 纠结|硬杠红米Note9Pro?iQOO Z1跌至1575,对比之后纠结了!
- 王兴称美团优选目前重点是建设核心能力;苏宁旗下云网万店融资60亿元;阿里小米拟增资居然之家|8点1氪 | 美团
- 长安|长安傍上华为这个大腿,市值暴涨500亿!可见华为影响力之大?
- 巅峰|realme巅峰之作:120Hz+陶瓷机身+5000mAh 做到了颜值与性能并存
- 蛋壳公寓|官媒发声:绝不能让“割韭菜者”一跑了之!
- 看过明年的iPhone之后,现在下手的都哭了
- 直播销售员|石家庄桥西区插上“互联网+”智慧发展之翼
- 精英|业务流程图怎么绘制?销售精英的经验之谈
- 砍单|iPhone12之后,拼多多又将iPhone12Pro拉下水
- 报名啦!宿迁开展第五届“十大科技之星”评选