动态地给一个对象添加一些额外的职责,就增加功能来说,Decorator模式相比生成子类更为灵活
别名:包装器Wrapper
有时我们希望给某个对象而不是整个类添加一些功能,例如:一个图形用户界面工具箱允许你对任意一个用户界面组件添加一些特性,例如边框。
使用继承机制是添加功能的一种有效途径,但这种方法不够灵活,因为边框的选择是静态的,用户不能控制对组件加边框的方式和时机。一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加边框,我们称这个嵌入的对象为装饰。
说人话就是:
【产品】:开发小哥,我这里有一份代码,你需要调用它的功能并补充公司的额外功能但是不能动它本身的内容,能做到吗?
【开发】:哈?怎么可能!怎么可能不改代码还要他功能,还得有额外的功能?难道让我写成这样的?
void demo () { // 调用原有代码功能 // do(); // 调用公司功能 // doMine(); } 复制代码
【BOSS】:磕大头!你不觉得这样很low吗?
【开发】:可是不这么写我咋改写?
【BOSS】:你仔细看看原有的代码,它们都实现了同样的接口,这就是一个突破点
【开发】:我去研究研究....
于是乎,我们开启了关于设计模式的经典书籍阅读之旅
/** * 装饰器模式共同的接口 */ public interface Component { String getName(); double getSpend(); } /** * 原本的类 */ public class ConcreteComponent implements Component { private String name; public ConcreteComponent(String name) { this.name = name; } @Override public String getName() { return name; } @Override public double getSpend() { return 10; } } /** * 装饰器类 注意它利用了组合的方式,同时注意函数实现的部分 */ public class MilkDecorator implements Component { Component coffe; MilkDecorator(Component coffe) { this.coffe = coffe; } @Override public String getName() { return coffe.getName() + ", 牛奶"; } @Override public double getSpend() { return coffe.getSpend() + 2D; } } 复制代码
装饰器模式的设计思路:
简单来说,
❝如果看着有点模棱两可,就看完本文后,访问专题设计模式开源项目,里面有具体的代码示例,链接在最下面
❞
在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责
Java 中最著名的装饰者模式的应用,就是 java.io 包中的各种InputStream 、Reader和 Writer 的实现类了。如果我们要从文件中读取文本内容,我们可以使用 FileReader(装饰者) 和 FileInputStream(装饰者);
但是如果我们想让读取的速度更快,那么我们就需要 BufferedReader(装饰者) ,这只需要改变一行代码就能实现
「附上GOF一书中对于装饰器模式的UML图:」
GitHub地址