设计模式第六讲--装饰模式 Decorator
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模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。
posted on 2021-12-07 23:21 xcxfury001 阅读(40) 评论(0) 收藏 举报
浙公网安备 33010602011771号