zoukankan      html  css  js  c++  java
  • 设计模式---装饰器模式

    装饰模式定义:装饰模式动态的将责任附加到对象上,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案。

    以大话设计模式中的例子来描述,
    1,找出概念
    装饰对象:人,(中国人,美国人等)
    装饰器:鞋子、裤子、帽子、外套

    2,既然要使用鞋子、裤子等装饰一个对象:人,则为穿了鞋子的人、穿了裤子的人、戴了帽子的人、穿了外套的人;其实都是在对人做装饰,且人原有的行为(接口函数)不能变;
    为了让穿了鞋子的人和中国人保持统一的行为,需要定义一个抽象接口,让中国人和穿鞋子的人都继承这个接口;
    我们定义这个接口为person,然后定义相关中国人,穿了鞋子的人等类,
    另外穿了鞋子的人既然要装饰人就要拥有一个人成员来装饰,根据依赖倒置原则(高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象),所以在Shoe类中保存一个Persion指针(实际为Chinese类对象指针);

    4,

    目前的类图可以发现,所有装饰类中都有一个persion对象,根据重构中重复代码应该提取到父类原则,应该把persion_对象提取到父类Persion中,但那样的话类图很奇怪,类自己包含自己类型的一个成员对象(目前这种代码结构只在单例中存在);


    5,
    因此,我们需要提取一个父类来保存共有的成员对象persion_且要保持原有接口,Decorator类就诞生了,我们把persion_对象提取到Decorator类中,并且让Decoreator继承Persion类来保持原有的接口Show()的一致性;

     (这里有一个比较有意思的现象:Decorator继承了Persion(保持接口的一致性),还保存了一个Persion指针类型的成员变量(是从各装饰子类提取的公共部分),这种代码结构目前只会在装饰模式中出现,以后如果看到代码里有这种结构,可以往装饰模式的角度阅读代码)

    6,
    现在的类图好看多了

    完整代码如下:

      1 #include <iostream>
      2 #include <string>
      3 
      4 class Persion {
      5  public:
      6   Persion() = default;
      7   virtual ~Persion() {}
      8 
      9   virtual void Show() = 0;
     10 
     11 };
     12 
     13 class Chinese : public Persion {
     14  public:
     15   Chinese() = default;
     16   ~Chinese() {}
     17 
     18   virtual void Show() override {
     19     std::cout << name_ << std::endl;
     20   }
     21 
     22   void SetName(const std::string& name) {
     23     name_ = name;
     24   }
     25 
     26  private:
     27   std::string name_;
     28 };
     29 
     30 class Decorator : public Persion {
     31  public:
     32   Decorator() = default;
     33   Decorator(Persion* persion) : persion_(persion) {}
     34   ~Decorator() = default;
     35 
     36   virtual void Show() override {}
     37   
     38  protected:
     39   Persion* persion_;
     40 };
     41 
     42 class Shoe : public Decorator {
     43  public:
     44   Shoe(Persion* persion) : Decorator(persion) {
     45   }
     46 
     47   ~Shoe() = default;
     48 
     49   virtual void Show() override {
     50     persion_->Show();  // 此写法为正序
     51     std::cout << "穿鞋子" << std::endl;
     52     // persion_->Show();  // 此写法为倒序
     53   }
     54 };
     55 
     56 class Trousers : public Decorator {
     57  public:
     58   Trousers(Persion* persion) : Decorator(persion) {
     59   }
     60 
     61   ~Trousers() = default;
     62   virtual void Show() override {
     63     persion_->Show();
     64     std::cout << "穿裤子" << std::endl;
     65   }
     66 };
     67 
     68 class Hat : public Decorator {
     69  public:
     70   Hat(Persion* persion) : Decorator(persion) {
     71   }
     72 
     73   ~Hat() = default;
     74   virtual void Show() override {
     75     persion_->Show();
     76     std::cout << "戴帽子" << std::endl;
     77   }
     78 };
     79 
     80 class Coat : public Decorator {
     81  public:
     82   Coat(Persion* persion) : Decorator(persion) {
     83   }
     84 
     85   ~Coat() = default;
     86 
     87   virtual void Show() override {
     88     persion_->Show();
     89     std::cout << "穿外套" << std::endl;
     90   }
     91 };
     92 
     93 int main(int argc, char** argv) {
     94   Chinese xm;
     95   xm.SetName("小明");
     96   
     97   Trousers trous(&xm);
     98   Shoe shoe(&trous);
     99   Coat coat(&shoe);
    100   Hat hat(&coat);
    101 
    102   hat.Show();
    103 
    104   return 0;
    105 }
    View Code

    运行结果:

     

  • 相关阅读:
    HTMLTestRunner下载生成报告
    python+selenium+chromewebdriver或Firefox的环境搭建
    unittest单元测试(简单算法题)
    APP测试功能点大全
    selenium元素定位
    博弈问题dp模版
    位运算基本操作
    素数模版
    二分查找模版
    计算机网络重要知识点
  • 原文地址:https://www.cnblogs.com/guoliushui/p/12222752.html
Copyright © 2011-2022 走看看