父博文地址:设计模式 - Design Patterns
一、是什么
-
问题
使用继承是静态的扩展:
- 随着系统功能增多造成了类数量指数级增加。
- 且基类的功能并不适用于所有子类。
-
寻找一个设计模式原则
开闭原则:类应该对扩展开放,对修改关闭。换句话说:在不修改类的前提下扩展类。
-
装饰者模式定义
动态的将责任附加到对象 上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
类图如下:
二、问答
-
及其子类依然继承自AbstractDecorator
AbstractComponent
不是吗?
我们依然使用了继承,的确如此。不过这么做的重点在于,装饰者和被装饰者需要是同一个类型,这很关键。我们只是利用继承达到“类型匹配”,而不是利用继承获取“行为”。
-
加入行为
我们不是通过继承来“加入新行为”,而是通过“组合”。
-
为什么装饰者是抽象类?
通常使用抽象类,当然Java 中也可以使用接口,此时需要把构造函数定义在各个装饰者子类中。
三、实例
1. FilterInputStream
是 InputStream
的装饰器
FilterInputStream
InputStream
类图如下:
- 介绍
是抽象被装饰类,InputStream
,ObjectInputStream
,FileInputStream
等是可以被装饰的具体组件。ByteArrayInputStream
是装饰者类(这里没有设计为抽象),FilterInputStream
,BufferedInputStream
,LineNumberInputSream
等是具体的装饰者类。DataInputSream
-
代码FilterInputStream
可以看到,包装类只有一个有参数的构造函数,参数是被包装类。包装类可以动态的添加功能,这里覆盖了public class FilterInputStream extends InputStream { protected volatile InputStream in; protected FilterInputStream(InputStream in) { this.in = in; } public int read() throws IOException { return in.read(); } // others }
并简单的调用被包装类的同名方法。read()
- 一个可能的用例
被FileInputSream
装饰,BufferedInputSream
又被BufferedInputSream
装饰。LineNumberInputSream