设计动机
- 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
- 如何使‘对象功能的扩展”能够根据需要来动态地实现?同时避免扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?
定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)
结构
例子
传统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| class Stream{ public: virtual char Read(int number)=0; virtual void Seek(int position)=0; virtual void Write(char data)=0; virtual ~Stream(){} };
class FileStream: public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class NetworkStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class MemoryStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class CryptoFileStream :public FileStream{ public: virtual char Read(int number){ FileStream::Read(number); } virtual void Seek(int position){ FileStream::Seek(position); } virtual void Write(byte data){ FileStream::Write(data); } };
class CryptoNetworkStream : :public NetworkStream{ public: virtual char Read(int number){ NetworkStream::Read(number); } virtual void Seek(int position){ NetworkStream::Seek(position); } virtual void Write(byte data){ NetworkStream::Write(data); } };
class CryptoMemoryStream : public MemoryStream{ }; class BufferedFileStream : public FileStream{ }; class BufferedNetworkStream : public NetworkStream{ }; class BufferedMemoryStream : public MemoryStream{ }
class CryptoBufferedFileStream :public FileStream{ public: virtual char Read(int number){ FileStream::Read(number); } virtual void Seek(int position){ FileStream::Seek(position); } virtual void Write(byte data){ FileStream::Write(data); } }; void Process(){ CryptoFileStream *fs1 = new CryptoFileStream();
BufferedFileStream *fs2 = new BufferedFileStream();
CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();
}
|
装饰模式
有时候组合方式会好于继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| class Stream{ public: virtual char Read(int number)=0; virtual void Seek(int position)=0; virtual void Write(char data)=0; virtual ~Stream(){} };
class FileStream: public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class NetworkStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class MemoryStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class CryptoStream: public Stream { Stream* stream;
public: CryptoStream(Stream* stm):stream(stm){ } virtual char Read(int number){ stream->Read(number); } virtual void Seek(int position){ stream::Seek(position); } virtual void Write(byte data){ stream::Write(data); } };
class BufferedStream : public Stream{ Stream* stream; public: BufferedStream(Stream* stm):stream(stm){ } }; void Process(){ FileStream* s1=new FileStream(); CryptoStream* s2=new CryptoStream(s1); BufferedStream* s3=new BufferedStream(s1); BufferedStream* s4=new BufferedStream(s2); }
|
可以看出CryptoStream类和BufferedStream类都含有相同的Stream指针成员,可以继续向上合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| class Stream{ public: virtual char Read(int number)=0; virtual void Seek(int position)=0; virtual void Write(char data)=0; virtual ~Stream(){} };
class FileStream: public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class NetworkStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
class MemoryStream :public Stream{ public: virtual char Read(int number){ } virtual void Seek(int position){ } virtual void Write(char data){ } };
DecoratorStream: public Stream{ protected: Stream* stream; DecoratorStream(Stream * stm):stream(stm){ } };
class CryptoStream: public DecoratorStream { public: CryptoStream(Stream* stm):DecoratorStream(stm){ } virtual char Read(int number){ stream->Read(number); } virtual void Seek(int position){ stream::Seek(position); } virtual void Write(byte data){ stream::Write(data); } }; class BufferedStream : public DecoratorStream{ public: BufferedStream(Stream* stm):DecoratorStream(stm){ } };
void Process(){ FileStream* s1=new FileStream(); CryptoStream* s2=new CryptoStream(s1); BufferedStream* s3=new BufferedStream(s1); BufferedStream* s4=new BufferedStream(s2); }
|
总结
-
通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差’’和“多子类衍生问题”。
-
Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。
-
Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”一是为“装饰”的含义