设计模式的代码十分难写的,要充分的体现可复用性,网上有着大量关于设计模式的代码,其中很多的代码违背了很多设计原则,比如依赖倒置原则、开放封闭原则,需要我们明辨是非。
设计模式的原则大于使用哪个设计模式,类的组合关系也大于类的继承,通过不断的写代码加上多思考多总结才能真正的领悟大师们的思想。
以下源代码第一份和第二份是我摘录课程的源码,第三份是经过我自己的想法与总结写的,我也建议大家学习一个模式,先动手把最初的代码改一改,这样能增加对这个模式的理解,而不是老师讲了什么才知道什么。
第一份代码
先让我们看看第一份代码,FileStream、 NetworkStream、MemoryStream要重写Read等一系列虚函数,这个是没问题的。可以当他们要实现一个功能的时候(加密呀等等功能,实现的功能不需要重写),而如果继续采用继承的话,功能分别继承FileStream、 NetworkStream、MemoryStream这些类,多一个功能,就要改变N个类,这样的维护性大大的减少了。这也违反了依赖倒置原则,高层模块不应该依赖低层模块,**应该都依赖抽象(基类)**我们进行改正一下,往下翻看第二份代码
//第一版代码
//业务操作
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();
}
第二份代码
对额外的功能新增一个基类,在使用组合的方式替代继承,提高代码复用性,在实际的工程已经可以了。对象Stream* stream并没有得到复用,在细致的话就要引出装饰模式,往下翻看第三份代码
//业务操作
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);
}
第三份代码
给所有的功能在套上一个基类(Decorate类),Stream的对象也能得到了复用
//业务操作
class Stream {
public:
virtual char Read(int number) = 0;
virtual void Seek(int position) = 0;
virtual void Write(int data) = 0;
virtual ~Stream() {}
};
//主体类
class FileStream : public Stream {
public:
virtual char Read(int number) {
//读文件流
}
virtual void Seek(int position) {
//定位文件流
}
virtual void Write(int data) {
//写文件流
}
};
class NetworkStream :public Stream {
public:
virtual char Read(int number) {
//读网络流
}
virtual void Seek(int position) {
//定位网络流
}
virtual void Write(int data) {
//写网络流
}
};
class MemoryStream :public Stream {
public:
virtual char Read(int number) {
//读内存流
}
virtual void Seek(int position) {
//定位内存流
}
virtual void Write(int data) {
//写内存流
}
};
class Decorator :public Stream {
//继承了这个类并且声明这个类的对象99%的可能性就是装饰模式了
public:
//为什么需要Decorator?
//因为这个Steam对象也是共用的,并且会有多个扩展操作,
//这样也使用了依赖倒置原则,具体的类(File、Network...)与
//可扩展的类(具体操作)通过Decorator这个抽象实现的通信
//Decorator通过他的上层Stream来进一步通信
Stream* stm; // new Stream();
Decorator(Stream* stm) :stm(stm) {
}
};
//扩展操作
//增加新的共用的功能,通过组合的形式,而不是每个类通过继承上一个类解决问题
class CryptoStream :public Decorator {//这样三种文件都可以通过这样的一个类
public:
CryptoStream(Stream* stm) : Decorator(stm) {}
virtual char Read(int number) {
//额外的加密操作...
stm->Read(number);//读文件流
}
virtual void Seek(int position) {
//额外的加密操作...
stm->Seek(position);//定位文件流
//额外的加密操作...
}
virtual void Write(int data) {
//额外的加密操作...
stm->Write(data);//写文件流
//额外的加密操作...
}
};
class BufferedStream : public Decorator {
//...
};
class CryptoBufferedStream :public Decorator {
public:
virtual char Read(int number) {
//额外的加密操作...
//额外的缓冲操作...
stm->Read(number);//读文件流
}
virtual void Seek(int position) {
//额外的加密操作...
//额外的缓冲操作...
stm->Seek(position);//定位文件流
//额外的加密操作...
//额外的缓冲操作...
}
virtual void Write(int data) {
//额外的加密操作...
//额外的缓冲操作...
stm->Write(data);//写文件流
//额外的加密操作...
//额外的缓冲操作...
}
};
void Process() {
//运行时装配
Stream* f = new FileStream();
Decorator* fs1 = new CryptoStream(f);
Stream* f2 = new CryptoStream(f);
//BufferedFileStream* fs2 = new BufferedFileStream();
// CryptoBufferedFileStream* fs3 = new CryptoBufferedFileStream();
}