1. “单一职责”模式
在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
典型模式
Decorator
Bridge
2. 动机(Motivation)
在某些情况下我们可能会“过度的使用继承来扩展对象的功能”,由于继承为类型引入的静态特质(没有变化的可能性),使得这种扩展方式缺乏灵活性;并且随着子类增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
如何使“对象功能的扩展”能够根据需求来动态的实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低。
3.代码
//业务操作 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 CrytoFileStream :public FileStream { public: virtual char Read(int number) { //额外的加密操作。。。 FileStream::Read(number); //读文件流 } virtual void Seek(int position) { //额外的加密操作。。。 FileStream::Seek(position); //定位文件流 } virtual void Write(char data) { //额外的加密操作。。。 FileStream::Write(data);//写文件流 } }; //扩展操作 class CrytoNetworkStream :public NetworkStream { public: virtual char Read(int number) { //额外的加密操作。。。 NetworkStream::Read(number); //读网络流 } virtual void Seek(int position) { //额外的加密操作。。。 NetworkStream::Seek(position); //定位网络流 } virtual void Write(char data) { //额外的加密操作。。。 NetworkStream::Write(data);//写网络流 } }; //扩展操作 class CrytoMemoryStream :public MemoryStream { public: virtual char Read(int number) { //额外的加密操作。。。 MemoryStream::Read(number); //读内存流 } virtual void Seek(int position) { //额外的加密操作。。。 MemoryStream::Seek(position); //定位内存流 } virtual void Write(char data) { //额外的加密操作。。。 MemoryStream::Write(data);//写内存流 } }; class BufferdFileStream :public FileStream { //... }; class BufferedNetworkStream :public NetworkStream { //... }; class BufferedMemoryStream :public MemoryStream { //... }; class CryptoBufferedFileSream :public FileStream { public: virtual char Read(int number) { //额外的加密操作 //额外的缓冲操作 FileStream::Read(number); //读文件流 } virtual void Seek(int position) { //额外的加密操作 //额外的缓冲操作 FileStream::Seek(position); //定位文件流 } virtual void Write(char data) { //额外的加密操作 //额外的缓冲操作 FileStream::Write(data);//写文件流 } }; void Process() { //编译时装配 CrytoFileStream* fs1 = new CrytoFileStream(); BufferdFileStream* fs2 = new BufferdFileStream(); CryptoBufferedFileSream* fs3 = new CryptoBufferedFileSream(); }
类之间的继承关系如下图所示:
采用Decorator模式修改完成之后的代码如下:
//业务操作 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 DecoratorStream :public Stream { protected: Stream* stream; //... DecoratorStream(Stream* s) :stream(s) {}; }; //扩展操作 class CrytoStream :public DecoratorStream //这个地方继承Stream只是为了遵循接口规范。 { public: //构造器 CrytoStream(Stream* s) :DecoratorStream(s) { } virtual char Read(int number) { //额外的加密操作。。。 stream->Read(number); } virtual void Seek(int position) { //额外的加密操作。。。 stream->Seek(position); } virtual void Write(char data) { //额外的加密操作。。。 stream->Write(data); } }; class BufferdStream :public DecoratorStream { public: BufferdStream(Stream* s) :DecoratorStream(s) { } virtual char Read(int number) { //额外的缓冲操作。。。 stream->Read(number); } virtual void Seek(int position) { //额外的缓冲操作。。。 stream->Seek(position); } virtual void Write(char data) { //额外的缓冲操作。。。 stream->Write(data); } }; void Process() { //运行时装配 FileStream* s1 = new FileStream(); CrytoStream* s2 = new CrytoStream(s1); BufferdStream* s3 = new BufferdStream(s1); BufferdStream* s4 = new BufferdStream(s2); //既加密又缓存 }
各类之间的继承关系图
4. 模式定义
动态(组合)的给一个对象增加一些额外的职责,就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。
5. 结构
6. 要点总结
通过采用组合而非继承的手法,Decorator模式实现了在运动时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。
Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。