博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式学习总结:(5)装饰模式
阅读量:4594 次
发布时间:2019-06-09

本文共 3459 字,大约阅读时间需要 11 分钟。

装饰模式:

顾名思义,就是装饰,比如手机套,用来装饰手机,但是,作为手机套的实现是不影响手机的,手机套就像一个装饰器。在比方,相框,相框花边,他们都是为了给相片添加新的额外的功能,但是这种功能本身不影响相片的性质。

行为模式

意图:

动态给一个对象添加额外的职责。就增加功能而言,装饰模式相比生成子类更为灵活。

 

比生成子类更灵活,确实,相比用继承方式去添加职责,装饰器模式表现非常灵活。

 比如这样的例子,流操作,一开始有文件流和网络流,如果用继承的方式,我想得这样写:

class Stream{public:    virtual handleStream()=0;    virtual ~Stream(){}     };

文件流:

#include
using namespace std;class FileStream: public Stream{public: FileStream(){} virtual ~FileStream(){} void handleStream(){ cout<<"处理文件流"<

网络流:

#include
using namespace std;class NetwordStream: public Stream{public: NetwordStream(){} virtual ~NetwordStream void handleStream(){ cout<<"网络流"<

 

如果要加密两种流,用继承我们还得这么写:

class CryptoFileStream :public FileStream{public:    CryptoFileStream():FileStream(){}    virtual ~CryptoFileStream();    void handleStream()    {         FileStream::handleStream();         cout<<"加密"<
class CryptoFileStream :public NetwordStream{public:    CryptoFileStream():NetwordStream(){}    virtual ~CryptoFileStream();    void handleStream()    {         NetwordStream::handleStream();         cout<<"加密"<

 

假如还有个转码的装饰类,那我们还得再写两个这样的类,我这里就不写了,不仅代码冗余,而且类膨胀严重。如果有n种具体子类和m中搭配装饰,粗略算一下应该要1+n+n*m+n*(2^m-m-1)个类,基类一个,然后有多少种子类可能就是n,而对类进行单一装饰是n*m种类,m种装饰器的搭配方式应该是2^m-m-1(二项式公式减前两项),n种子类就有n*(2^m-m-1).

当然,这不是重点,重点是我们用装饰模式可以如何实现,先看看书上给的结构图:

 

 

我们看到四个基本的角色:

1.抽象接口对象(component)

    最基本的机构对象,用于动态添加职责

2.具体的实际对象,具有具体职责的对象(concrete component)

3.总装饰器(decorator)

  需要保存一个component对象用于多态,同时继承component用于添加额外职责。

4.具体装饰

  实现你需要实现的额外职责。

 

最基本的基类:

class AbStream{public:    virtual void handleBuff()=0;    virtual ~AbStream(){}};

文件流类:

class FileStream:public AbStream{public:    FileStream(){}    virtual ~FileStream(){}    void handleBuff();};void FileStream::handleBuff(){    cout << "处理文件流" << endl;}

网络流:

class NetwordStream:public AbStream{public:    NetwordStream();    virtual ~NetwordStream();    void handleBuff();};void NetwordStream::handleBuff(){    cout << "处理网络流" << endl;}

 

接下来是装饰器:

class StreamDocorator:public AbStream{public:    virtual ~StreamDocorator();    void handleBuff();protected:    StreamDocorator(AbStream *stream) :_stream(stream)    {    }private:    AbStream *_stream;};void StreamDocorator::handleBuff(){    _stream->handleBuff();}

  StreamDocorator::~StreamDocorator()

  {

 

  }

 

然后是加密,作为具体装饰类:

class CryptoStream :public StreamDocorator{public:    CryptoStream(AbStream *stream) : StreamDocorator(stream){}    virtual ~CryptoStream(){}    void handleBuff()    {        StreamDocorator::handleBuff();        cout << "对数据流加密" << endl;    }};

如果还有转码:

class BuffStream :public StreamDocorator{public:    BuffStream(AbStream *stream) :StreamDocorator(stream){}    virtual ~BuffStream(){}    void handleBuff()    {        StreamDocorator::handleBuff();        cout << "二进制转码" << endl;    }};

 

然后我们就可以测试一下:

int main(){    FileStream *a = new FileStream();    CryptoStream *cS = new CryptoStream(a);    cS->handleBuff(); cout << "----------------------" << endl;    BuffStream *bcS = new BuffStream(cS);  //还可以进行复合装饰    bcS->handleBuff();    return 0;}

运行后的结果:

 

对比装饰模式和策略模式:

最根本的是装饰模式对于服务的对象是透明的,这个服务的对象就好比上面例子中的FileStream,透明应该这么理解,对于FileStream,它完全不知道有装饰器这样的兄弟,装饰器存不存在对于FileStream并没有什么影响,而策略模式中,比如上次例子中的Economic类,实际上用策略模式也能实现FileStream这个逻辑,但是对于FileStream,它需要保持关于装饰器(策略类,这里假设是策略模式实现)的引用,那么这是不透明。

而且如果抽象Stream如果过于复杂,用策略模式也是比较好的选择,当然,装饰器更加强调了多种可能(指装饰和策略)的搭配,而策略好像并无法达成这个要求。

当然,最后的还是要感慨下,也许在以后的开发过程中能够领悟更多,毕竟古人常说:"纸上得来终觉浅,绝知此事要躬行".

 

转载于:https://www.cnblogs.com/wuweixin/p/5425932.html

你可能感兴趣的文章
南阳oj 语言入门 A+B paoblem 题目477 题目844
查看>>
ffmpeg 内存池
查看>>
双语小说阅读:《谁动了我的奶酪》
查看>>
linux touch和vi建立的文件是什么文件类型的
查看>>
3-9
查看>>
导航右侧添加按钮、隐藏导航条和状态栏
查看>>
第二阶段冲刺6
查看>>
Java中final关键字的用法
查看>>
URL重写
查看>>
快速超越Chrome 微软IE9最新功能详解
查看>>
今天写一注册机时遇到猥亵的cookie设置。
查看>>
22万个木箱!TWaver 3D极限压榨
查看>>
NPOI使用手册
查看>>
GIT 常用命令
查看>>
php接收二进制文件转换成图片
查看>>
C++虚函数原理(转)
查看>>
InnoDB存储引擎介绍-(6) 一. Innodb Antelope 和Barracuda区别
查看>>
字典树的动态与静态模板
查看>>
sscanf的最基础用法(非原创)
查看>>
A new start
查看>>