• 【结构型】Decorate模式


        装饰模式主要意图是为对象扩展额外的职责,但对于用户来说,在使用行为上并没有任何的变化。在此举一个例子来解释该模式的含义。假如你手上有一张照片,此时可以给它盖上一片玻璃片,同时再套上一个精美的相框。如此相片就更好看同时又被更好地防护起来。此处的玻璃片以及相框,对于原来的照片来说,都是起到一个装饰的作用。并且,加上这些装饰后的照片,你能说它不是照片吗?不,它还是一个照片,是一个被精美装饰过后的照片。

        在编程设计上,上面例子可描述如下:

     1 class IImage
     2 {
     3 public:
     4     // 图像总是要被绘制出来的
     5     virtual void draw() {}
     6 };
     7 class Photograph : public IImage
     8 {
     9 public:
    10     // some code here........
    11 };
    12 class PhotograhDecorate : public IImage
    13 {
    14 public:
    15     // some code here........
    16     
    17 protected:
    18     inline IImage* getImage() { /* some code here........*/ }
    19 
    20 private:
    21     IImage* _image;
    22 };
    23 class GlassDecorate : public PhotograhDecorate
    24 {
    25 public:
    26     virtual void draw() override {
    27         getImage()->draw();
    28         this->drawGlass();
    29     }
    30     
    31 private:
    32     void drawGlass() {
    33         // some code here........
    34     }
    35 
    36 };
    37 
    38 class FrameDecorate : public PhotograhDecorate
    39 {
    40 public:
    41     virtual void draw() override {
    42         getImage()->draw();
    43         this->drawFrame();
    44     }
    45     
    46 private:
    47     void drawFrame() {
    48         // some code here........
    49     }
    50 
    51 };
    相片装饰编码参考

        由上面的定义以及例子,可以看出装饰其实是可以无限嵌套下去的。给相片装饰完了玻璃,接着又将装饰完玻璃后的相片一起用相框给装饰上。装饰模式的类关系结构图参考如下:

        装饰模式的优缺点分析:

        1) 如果前面的相片例子中,不使用装饰模式的话,则用户期望想要一张盖上玻璃片的相片的话,则需要从Photograph类继承下来实现一个玻璃片相片类。如果再想要一个带相框效果的照片,则又需要继承一个分支出来。如果想要一张盖上玻璃片又带相框的照片,则又需要第三个分支。试想下,如果此时还有第三种装饰情况了?比如:在照片的右下角有明星签名显示。那子类的数量就多了N种了。子类的数量是相于当所有装饰效果的组合。如此下去,随着装饰效果种类的增加,Photograph的类系将十分复杂,增量方式是以所有装饰效果的组合数量增长了。

        此时如果使用装饰模式,则只需要N个的装饰类即可。需要什么效果,就新增一个装饰类即可。因此,扩展效果十分方便,效果的新增也不会引起Photograph类系的动荡。所写的任何装饰效果都是可以随意组合使用,而且对用户来说,使用上与直接使用照片Photograph类,没有任何区别。

        2) 由于增加了装饰类系,因此,系统中就多了许多附加的类。如果一个相片拥有100种附加效果,则就需要增加100个装饰类。这其实也会给系统维护增加难度。

        3) 某一类系的装饰类,只是针对某一对象装饰。如果系统中有非常多的对象都有它们自己的装饰类,上面第2)的问题就更加严重。

        4) 在使用装饰框时,如果待装饰的对象较为复杂时,比如:前面例子中的相片类很复杂时,则它的装饰类系的实现难度会很大。因此,实现代价也会随之增加。从此点看,在动手设计装饰类前,需要先考虑清楚。

  • 相关阅读:
    mac 鼓捣php 多版本切换
    thinkPHP 导出excel 发布正式环境net::ERR_INVALID_RESPONSE
    js 计时显示 倒着 正者 都行
    LNMP 下 php.ini 文件修改后不生效
    Jquery 遍历数组之$().each方法与$.each()方法介绍
    js 去掉字符串最后一个逗号
    js拼接字符串时,字符串首出现undefined的问题
    PHP 暂停函数 sleep() 与 usleep() 的区别
    在IDEA里创建web项目,以及web 项目部署
    spring容器和springmvc容器,以及web容器的关系
  • 原文地址:https://www.cnblogs.com/tongy0/p/5529884.html
Copyright © 2020-2023  润新知