今天学习了桥模式,但是,我发现它和装饰模式有很像的地方。
书上对桥模式的定义很容易的想到桥模式可能重点在于两种不同维度的分离,而装饰模式更多强调在原有基础上扩展,即使很容易感觉到这一点,但是我还是觉得很不放心,毕竟再次之前都没有接触过类似的业务。
关于桥模式定义是这样的:
意图
将抽象部分和它的实现部分分离,使得它们可以独立地变化。
结构图如下:
其中有四个 基本角色:
抽象接口类(Abstraction)
定义抽象类的接口
保留一个实现接口类(Implementor)对象的指针。
扩充类(RefinedAbstraction)
扩充Abstraction的接口。
实现基类(Implementor)
实现类的接口
具体实现类(ConcreteImplementor)
定义接口
为了弄明白装饰模式和桥模式的区别,我对上一次学的装饰模式例子进行了改写,依照上面的结构,我的思路是把加密和转码这样的装饰器当成抽象维度,而fileStream和networkStream作为实现维度。
所以就有了如下的代码:
实现维度的代码:
class StreamImp { public: StreamImp(){} ~StreamImp(){} virtual void iHandleStream()=0; };
FileStream:
class FileStreamImp :public StreamImp { public: void iHandleStream(); }; void FileStreamImp::iHandleStream() { cout << "处理文件流" << endl; }
Network:
class NetwordStreamImp :public StreamImp { public: void iHandleStream(); }; void NetwordStreamImp::iHandleStream() { cout << "处理网络流" << endl; }
然后是抽象维度:
class Stream { public: Stream(StreamImp *stream):_stream(stream){} ~Stream(){} virtual void handleStream()=0; private: StreamImp * _stream; }; void Stream::handleStream() { _stream->iHandleStream(); }
加密:
class CroStream:public Stream { public: CroStream(StreamImp *stream) :Stream(stream){} void handleStream(); }; void CroStream::handleStream() { Stream::handleStream(); cout << "加密流中。。。" << endl; }
转码:
class TranStream:public Stream { public: TranStream(StreamImp *stream) :Stream(stream){} void handleStream(); private: }; void TranStream::handleStream() { Stream::handleStream(); cout << "处理网络流中" << endl; }
然后我开始测试:
//必要的话引入头文件,我没写出 int main() { FileStreamImp * a = new FileStreamImp(); a->iHandleStream(); cout << "--------------------" << endl; CroStream * c = new CroStream(a); c->handleStream(); return 0; }
于是就看到了这样的结果
乍一看还是挺完美的:
然后,我相信其实到这里,大概也就能够看出了装饰模式和桥模式结构上那一点点不同,仅仅是一点点,确实真正的产生了很大的不同,就像它们的名字一样那么生动形象。
用桥模式实现的版本完全不支持同时加密转码两种操作,原因是它不像桥模式一样,两种维度有个共同的祖先,当然,对于装饰模式而言,我们看到因为他们有共同的祖先,所以实际上不能做到装饰和具体实现的完全分离,它更多是在已有接口的基础上添加新的职责,尽管桥模式也有这样的功能,但是桥模式在真正的把两个维度分开了,在复合添加职责上确没有装饰模式那么的灵活。在回头看看结构图,我想,也就一目了然。
当然最后还是要说一下,我感觉桥模式具体业务还是比较复杂的,在将业务分开之前,我想得考虑的足够长远,至少就我现在的水平,还是难以理解的,大概也就这样了,我想上面代码应该还有问题吧,以后再做补充。