使用继承的方法,如果职责划分不清晰,子类会急剧膨胀。
动机
过度使用继承的方式会出问题
案例
对各种流需要读写等。
第一种方式
直接采用继承的方式 只要再加一个网络数据流那么就会发生类爆炸
class Stream {
public:
//读数据流
virtual char Read(int num) = 0;
//写数据流
virtual void Write(char data) = 0;
//定位数据流
virtual void Seek(int position) = 0;
virtual ~Stream(){}
};
class FileStream:public Stream {
public:
//读数据流
virtual char Read(int num) {
qDebug()<<"读文件"<<endl;
}
//写数据流
virtual void Write(char data) {
qDebug()<<"写文件"<<endl;
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"定位到文件"<<endl;
}
};
//加密文件
class EncryptFileStream:public FileStream {
public:
//读数据流
virtual char Read(int num) {
qDebug()<<"加密文件"<<endl;
FileStream::Read(num);
}
//写数据流
virtual void Write(char data) {
qDebug()<<"加密文件"<<endl;
FileStream::Write(data);
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"加密文件"<<endl;
FileStream::Seek(position);
}
};
//缓冲
class BuffFileStream:public FileStream {
public:
//读数据流
virtual char Read(int num) {
qDebug()<<"缓冲文件"<<endl;
FileStream::Read(num);
}
//写数据流
virtual void Write(char data) {
qDebug()<<"缓冲文件"<<endl;
FileStream::Write(data);
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"缓冲文件"<<endl;
FileStream::Seek(position);
}
};
应用程序
BuffFileStream bstream ;
bstream.Read(10);
这里如果我们既需要加密又需要缓冲 而且需要网络流 内存流的时候就需要增加大量的代码
优化
优化第一步 将继承改为组合
//class Stream {
//public:
// //读数据流
// virtual char Read(int num) = 0;
// //写数据流
// virtual void Write(char data) = 0;
// //定位数据流
// virtual void Seek(int position) = 0;
// virtual ~Stream(){}
//};
//class FileStream:public Stream {
//public:
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"读文件"<<endl;
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"写文件"<<endl;
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"定位到文件"<<endl;
// }
//};
加密文件
//class EncryptFileStream {
//public:
// FileStream stream;
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"加密文件"<<endl;
// stream.Read(num);
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"加密文件"<<endl;
// stream.Write(data);
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"加密文件"<<endl;
// stream.Seek(position);
// }
//};
缓冲
//class BuffFileStream{
//public:
// FileStream stream;
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"缓冲文件"<<endl;
// stream.Read(num);
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"缓冲文件"<<endl;
// stream.Write(data);
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"缓冲文件"<<endl;
// stream.Seek(position);
// }
//};
优化第二步 将具体勒替换为接口 ,编译时变幻为执行时
//class Stream {
//public:
// //读数据流
// virtual char Read(int num) = 0;
// //写数据流
// virtual void Write(char data) = 0;
// //定位数据流
// virtual void Seek(int position) = 0;
// virtual ~Stream(){}
//};
//class FileStream:public Stream {
//public:
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"读文件"<<endl;
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"写文件"<<endl;
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"定位到文件"<<endl;
// }
//};
加密文件
//class EncryptFileStream: public Stream{
//public:
// Stream* stream;
// EncryptFileStream(Stream* stm):stream(stm){}
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"加密文件"<<endl;
// stream->Read(num);
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"加密文件"<<endl;
// stream->Write(data);
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"加密文件"<<endl;
// stream->Seek(position);
// }
//};
缓冲
//class BuffFileStream:public Stream{
//public:
// Stream* stream;
// BuffFileStream(Stream* stm):stream(stm){}
// //读数据流
// virtual char Read(int num) {
// qDebug()<<"缓冲文件"<<endl;
// stream->Read(num);
// }
// //写数据流
// virtual void Write(char data) {
// qDebug()<<"缓冲文件"<<endl;
// stream->Write(data);
// }
// //定位数据流
// virtual void Seek(int position) {
// qDebug()<<"缓冲文件"<<endl;
// stream->Seek(position);
// }
//};
//优化第三步 将相同的字段向上抽象
//这里每个都有Stream* stream;
//那我们是不是就要把这个属性放到Stream这个基类中呢?
//不可以的 因为FileStream 或者 NetStream不需要这个属性
//那么这里就抽象一个中间的类Decorate
class Stream {
public:
//读数据流
virtual char Read(int num) = 0;
//写数据流
virtual void Write(char data) = 0;
//定位数据流
virtual void Seek(int position) = 0;
virtual ~Stream(){}
};
class FileStream:public Stream {
public:
//读数据流
virtual char Read(int num) {
qDebug()<<"读文件"<<endl;
}
//写数据流
virtual void Write(char data) {
qDebug()<<"写文件"<<endl;
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"定位到文件"<<endl;
}
};
class Decorate :public Stream {
protected:
Stream* stream;
public:
Decorate(Stream * stm):stream(stm){
}
};
//加密文件
class EncryptFileStream: public Decorate{
public:
EncryptFileStream(Stream* stm):Decorate(stm){}
//读数据流
virtual char Read(int num) {
qDebug()<<"加密文件"<<endl;
stream->Read(num);
}
//写数据流
virtual void Write(char data) {
qDebug()<<"加密文件"<<endl;
stream->Write(data);
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"加密文件"<<endl;
stream->Seek(position);
}
};
//缓冲
class BuffFileStream:public Decorate{
public:
BuffFileStream(Stream* stm):Decorate(stm){}
//读数据流
virtual char Read(int num) {
qDebug()<<"缓冲文件"<<endl;
stream->Read(num);
}
//写数据流
virtual void Write(char data) {
qDebug()<<"缓冲文件"<<endl;
stream->Write(data);
}
//定位数据流
virtual void Seek(int position) {
qDebug()<<"缓冲文件"<<endl;
stream->Seek(position);
}
};
总结 :如果不仅继承一个类而且组合一个类,那么大概率这是一个装饰模式
class Decorate :public Stream {
protected:
Stream* stream;
public:
Decorate(Stream * stm):stream(stm){
}