先说一个反例:
我们有三个流类,继承自流基类:
- class Stream {
- protected:
- virtual void Read() = 0;
- virtual void Seek() = 0;
- virtual void Write() = 0;
- };
-
- class Stream1:public Stream {
- void Read() {
- //Stream1的读取方法
- }
- void Seek() {
- //Stream1的定位方法
- }
- void Write() {
- //Stream1的写方法
- }
- };
-
- class Stream2 :public Stream {
- void Read() {
- //Stream2的读取方法
- }
- void Seek() {
- //Stream2的定位方法
- }
- void Write() {
- //Stream2的写方法
- }
- };
-
- class Stream3 :public Stream {
- void Read() {
- //Stream3的读取方法
- }
- void Seek() {
- //Stream3的定位方法
- }
- void Write() {
- //Stream3的写方法
- }
- };
然后我们要对这3个类的留进行加密,我们可以用继承来写:
- class Stream {
- protected:
- virtual void Read() = 0;
- virtual void Seek() = 0;
- virtual void Write() = 0;
- };
-
- class Stream1:public Stream {
- public:
- virtual void Read() {
- //Stream1的读取方法
- }
- virtual void Seek() {
- //Stream1的定位方法
- }
- virtual void Write() {
- //Stream1的写方法
- }
- };
-
- class Stream2 :public Stream {
- public:
- virtual void Read() {
- //Stream2的读取方法
- }
- virtual void Seek() {
- //Stream2的定位方法
- }
- virtual void Write() {
- //Stream2的写方法
- }
- };
-
- class Stream3 :public Stream {
- public:
- virtual void Read() {
- //Stream3的读取方法
- }
- virtual void Seek() {
- //Stream3的定位方法
- }
- virtual void Write() {
- //Stream3的写方法
- }
- };
-
- class CryptoStream1 :public Stream1 {
- public:
- virtual void Write() {
- //加密
- //写方法
- }
- };
-
- class CryptoStream2 :public Stream2 {
- public:
- virtual void Write() {
- //加密
- //写方法
- }
- };
-
- class CryptoStream3 :public Stream3 {
- public:
- virtual void Write() {
- //加密
- //写方法
- }
- };
这里就有问题了,其中加密方法我们是不变的,用的是同一种加密算法,但是我们得写3遍,嗯....
bad smell;
我们可以采用装饰模式来解决这个问题
UML如下

其中Component是抽象接口,ConcreteComponent是具体的对象,Decorator是装饰器与Component之间的中间类,一般里面会有一个Component的指针,用来访问ConcreteComponent
Decorator与Component的关系很特殊,即是继承关系又是组合关系,继承关系是为了获取接口,组合关系是为了访问子类;
以下是个人的理解:
1:如果我们用继承来解决加密的需求,那么会给扩展出来的类加上编译时的静态特征,既然是静态,那么对于变化,就是不堪一击的,只要需求一遍,只能在修改静态特征,如果有其他类依赖这个类,那么很显然,牵一发动全身。
2:如果我们用装饰模式来解决加密的需求,那么我们可以获得动态的特征,我们可以随着需求的改变,动态地调整装饰器中的指针指向的子类,充分地利用了多态性,在开始的例子里面,我们添加新的流类,如果这个流类依然用的是让一个加密算法,那么Decorate不用变,如果我们增加新的加密算法,我们只需要继承Decorate写一个新的修饰类,而不用为每个流类设计一个新的加密类。
3:继承方式打破了设计模式八股文之:依赖倒置原则,即高层模块不依赖于低层模块。
其中加密类可以视为高层模块,其中流类是低沉模块,因为高层模块依赖了底层模块,所以限制了高层模块的扩展性。
也打破了八股文之优先使用对象组合,而不是类继承