设计模式基础(4):装饰模式
介绍装饰模式的C++示例代码、面向的问题、图解装饰模式核心思想
面向的需求
处理“过度地使用继承来扩展对象功能”。因为继承为类型引入了更多的静态特质,使得拓展方式缺乏灵活性,并且随着子类的增多,数量急剧扩张。
如何拓展对象的功能,并具有很大的动态性,以便于程序的后期维护。
示例代码
采用继承手段来拓展功能
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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| 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{ public: virtual char Read(int number){ MemoryStream::Read(number); } virtual void Seek(int position){ MemoryStream::Seek(position); } virtual void Write(byte data){ MemoryStream::Write(data); } };
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| 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); }
|
代码分析和思想
单纯继承下类的关系
采用装饰模式下类的关系
核心思想
- 要为原有的类拓展新功能。有时要注意到其实我们是在为某一抽象类增加功能,而不要贸贸然地去为某一个具体的类采用继承的方式。可能会导致类的种类过多,代码维护不方便。
- 通过组合的关系为某一个对象增加额外的职责,要更为灵活。
装饰模式类图关系
要注意到,装饰类既继承了基类,又在内部维护了一个基类对象(组合)。这是十分显著的特征。
关键点
- 技法上,采用组合的方式来拓展功能。
- 目标上,为了解决主体类在多个方向上扩展的功能,如何更好的动态拓展功能。