• 设计模式C++描述----10.装饰(Decorator)模式


    一. 举例

    我之前做过一个文件系统就叫 MyFileSys 吧,后来的话,客户想加入一些附加功能,比如压缩、加密、杀毒之类的操作,这些附加操作没有先后顺序,比如你可以先压缩再加密,也可以先杀毒再压缩,等等。

    这些附加功能是可选的,有的客户要这些功能,有的不要,有的要其中的几种附加功能等等。怎么设计呢?

    第一种方案:
    直接修改这个独立的文件系统 MyFileSys,对于不同的客户实现不同的文件系统。

    后来随着客户的增多,发现维护和修改的工作量越来越大。因为每增加一个客户就要重新生成一个类,然后把客户想要的附加功能加入,更加郁闷的是,只针对一个客户有时也是要修改很多次,客户今天要这些附加功能,明天又想加入另外一些功能,这样改来改去,维护工作量也是很大的。

    第二种方案:

    后来改用第二种方案,实现一个单独的附加功能类,保持原文件系统不变,这样在客户端就可以轻松的加入一些附加功能。

    代码如下:

    1. //定义一个对象接口,可以给这些对象动态地添加职责  
    2. class FileSys  
    3. {  
    4. public:  
    5.     virtual ~FileSys()  
    6.     {  
    7.     }  
    8.   
    9.     virtual void Operation()  
    10.     {  
    11.     }  
    12. protected:  
    13.     FileSys()  
    14.     {  
    15.     }  
    16. };  
    17.   
    18. //定义一个具体的对象  
    19. class MyFileSys:public FileSys  
    20. {  
    21. public:  
    22.     MyFileSys()  
    23.     {  
    24.     }  
    25.   
    26.     ~MyFileSys()  
    27.     {  
    28.     }  
    29.   
    30.     void Operation()  
    31.     {  
    32.         cout<<"MyFileSys operation..."<<endl;  
    33.     }  
    34. };  
    35.   
    36. //装饰抽象类  
    37. class Decorator:public FileSys  
    38. {  
    39. public:  
    40.     Decorator(FileSys* fileSys)  
    41.     {  
    42.         this->_fileSys = fileSys;  
    43.     }  
    44.   
    45.     virtual ~Decorator()  
    46.     {  
    47.         delete _fileSys;  
    48.     }  
    49.   
    50.     void Operation()  
    51.     {  
    52.     }  
    53. protected:  
    54.     FileSys* _fileSys;  
    55. };  
    56.   
    57. //压缩装饰类  
    58. class ZipDecorator:public Decorator  
    59. {  
    60. public:  
    61.     ZipDecorator(FileSys* fileSys):Decorator(fileSys)  
    62.     {  
    63.     }  
    64.   
    65.     ~ZipDecorator()  
    66.     {  
    67.     }  
    68.       
    69.     void Operation()  
    70.     {  
    71.         _fileSys->Operation(); //首先运行以前的功能  
    72.           
    73.         this->AddedZipBehavior(); //附加功能  
    74.     }  
    75.       
    76.     void AddedZipBehavior()  
    77.     {  
    78.         cout<<"Added Zip Behavior...."<<endl;  
    79.     }  
    80. };  
    81.   
    82. //杀毒装饰类  
    83. class KillVirDecorator:public Decorator  
    84. {  
    85. public:  
    86.     KillVirDecorator(FileSys* fileSys):Decorator(fileSys)  
    87.     {  
    88.     }  
    89.       
    90.     ~KillVirDecorator()  
    91.     {  
    92.     }  
    93.       
    94.     void Operation()  
    95.     {  
    96.         _fileSys->Operation();  
    97.           
    98.         this->AddedKillVirBehavior();  
    99.     }  
    100.       
    101.     void AddedKillVirBehavior()  
    102.     {  
    103.         cout<<"Added Kill Virus Behavior...."<<endl;  
    104.     }  
    105. };  
    106.   
    107. //加密装饰类  
    108. class EncryptDecorator:public Decorator  
    109. {  
    110. public:  
    111.     EncryptDecorator(FileSys* fileSys):Decorator(fileSys)  
    112.     {  
    113.     }  
    114.       
    115.     ~EncryptDecorator()  
    116.     {  
    117.     }  
    118.       
    119.     void Operation()  
    120.     {  
    121.         _fileSys->Operation();  
    122.           
    123.         this->AddedEncrypeBehavior();  
    124.     }  
    125.       
    126.     void AddedEncrypeBehavior()  
    127.     {  
    128.         cout<<"Added Encrypt Behavior...."<<endl;  
    129.     }  
    130. };  
    131.   
    132. //////////////////////////////////////////////////////////////////////////  
    133. //测试  
    134. int main()  
    135. {  
    136.     FileSys* fileSys = new MyFileSys();  
    137.       
    138.     Decorator* dec1 = new ZipDecorator(fileSys);  //在原文件系统上,加入压缩功能  
    139.     Decorator* dec2 = new KillVirDecorator(dec1); //在之前的基础上,加入杀毒功能  
    140.     Decorator* dec3 = new EncryptDecorator(dec2); //再加入加密功能  
    141.   
    142.     dec3->Operation();  
    143.   
    144.     return 0;  
    145. }  

    这样之后,如果要添加附加功能,实现起来就很方便了。这种模式就是装饰模式。

    二. 装饰模式

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

    说明:

    Componet,主要是定义一个接口,通过这个接口可以给这些对象(ConcreteComponent)添加职责。

    Dectorator,装饰类,通过外类(ConcreteDecorator)来扩展Component 类的功能,对于Component来说,是无需知道这个抽象类的存在的。

    ConcreteDecorator,具体装饰类,添加具体的附加功能。

    优点:

    1. 装饰类是为已有功能动态地添加更多功能的一种方式。

    2. 有效地把类的核心职责装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。

    三. 问题讨论

    从上图可以看到 Decorator 是继承于 Component 的,也就和 ConcreteComponent 成了兄弟了,但是 Decorator 的作用却是修饰 ConcreteComponent 的,这点好像是很怪怪的!!最说不通的是Decorator 与 Component 是没有is-a关系的!!

    我个人觉得:

    1. 这个继承关系,不应该是我们要重点关注的。这里使用继承主要是为了要重用 Operation() 这个接口,以达修饰的目的。

    2. 重点是 Decorator 与 Component 这个组合关系。装饰类里有一个Component 指针,正是由于它的存在才能修饰到具体的 Component 对象。

  • 相关阅读:
    三种负载均衡 Nginx、Dubbo、Ribbon 区别
    Docker基础学习
    主从复制报错2061:Authentication plugin 'caching_sha2_password' reported error:Authentication require secure connection
    LRU、LFU算法区别
    CAP理论原理
    Mysql安装服务到Window服务列表
    从零开始掌握 HAProxy 负载均衡器,详细!!
    一举拿下Nginx
    Nginx 负载均衡配置误区
    Linux自动化技巧
  • 原文地址:https://www.cnblogs.com/any91/p/3247993.html
Copyright © 2020-2023  润新知