首页 > 其他 > 详细

设计模式---装饰器模式

时间:2020-02-11 00:06:38      阅读:99      评论:0      收藏:0      [点我收藏+]

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

 

以大话设计模式中的例子来描述,
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

 

运行结果:

 

 

 技术分享图片

设计模式---装饰器模式

原文:https://www.cnblogs.com/guoliushui/p/12222752.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!