天天看點

c++設計模式----Decorator(裝飾)

裝飾模式:

            首先我回憶一下橋接模式:橋接模式的意圖是讓抽象和實作分離開來,讓兩者獨立的變化。而裝飾模式的重點在于裝飾,一個功能用一個簡單的類來表示裝飾的職責,這個簡單的類與他要裝飾的對象的類提供一緻的接口,這樣保持了接口的一緻性。我們要仔細分析橋接模式與裝飾模式兩者具體的實作而把他們區分開來。要熟悉各種設計模式是一個長時間的過程,不是一下子就能體會的,要多多去揣摩這樣的實作的意圖是什麼,仔細品味,就會發現容易混淆的模式也很容易區分開來。

           裝飾模式提供了更加靈活的向對象添加職責的方式。可以用添加和分離的方法,用裝飾在運作時刻增加和删除職責。裝飾模式提供了一種“即用即付”的方法來添加職責。它并不試圖在一個複雜的可定制的類中支援所有可預見的特征,相反,你可以定義一個簡單的類,并且用裝飾類給它逐漸地添加功能。可以從簡單的部件組合出複雜的功能。

意圖:

           動态地給一個對象添加一些額外的職責。就增加功能來說,Decorator 模式相比生成子類更為靈活。 

适用性:

           在不影響其他對象的情況下,以動态、透明的方式給單個對象添加職責。

           處理那些可以撤消的職責。

           當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充,為支援每一種組合将産生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隐藏,或類定義不能用于生成子類。

#include <iostream>
using namespace std;

class Component
{
public:
  virtual void Operation() = 0;
};

class concreteComponent :public Component
{
public:
  void Operation()
  {
    cout << "this is a concreteComponent, not a decorator." << endl;
  }
};

class Decorator :public Component
{
public:
  Decorator(Component *p) : p_Component(p) {}
  void Operation()
  {
    if (p_Component != NULL)
    {
      p_Component->Operation();
    }
  }

private:
  Component *p_Component;
};

class DecoratorA :public Decorator
{
public:
  DecoratorA(Component *p) : Decorator(p) {}
  void Operation()
  {
    add_status();
    Decorator::Operation();
  }

  void add_status()
  {
    cout << "I am DecoratorA. " << endl;
  }
};

class DecoratorB :public Decorator
{
public:
  DecoratorB(Component *p) : Decorator(p) {}
  void Operation()
  {
    add_bahavior();
    Decorator::Operation();
  }

  void add_bahavior()
  {
    cout << "I am DecoratorB. " << endl;
  }
};

int main(int argc, char*argv[])
{
  Component* object = new concreteComponent();
  Decorator *a = new DecoratorA(object);
  a->Operation();
  cout << "-----------------------------------------------------" << endl;

  Decorator *b = new DecoratorB(object);
  b->Operation();
  cout << "------------------------------------------------------" << endl;

  Decorator *ab = new DecoratorB(a);
  ab->Operation();
}      

我們來看一個實際的具體的例子:

          比如有一個手機,允許你為手機添加特性,比如增加挂件、螢幕貼膜等。一種靈活的設計方式是,将手機嵌入到另一對象中,由這個對象完成特性的添加,我們稱這個嵌入的對象為裝飾。這個裝飾與它所裝飾的元件接口一緻,是以它對使用該元件的客戶透明。

#include <iostream>
#include <string>
using namespace std;

//公共抽象類
class Phone
{
public:
  virtual void ShowDecorate() {}
};

//具體的手機類
class iPhone : public Phone
{
public:
  iPhone(string s) :name(s){}

  void ShowDecorate()
  {
    cout << "I am " << name << endl;
  }

private:
  string name;//手機名
};

//裝飾類
class DecoratorPhone : public Phone
{
private:
  Phone *m_phone;  //要裝飾的手機

public:
  DecoratorPhone(Phone *phone) : m_phone(phone) {}

  virtual void ShowDecorate() { m_phone->ShowDecorate(); }
};
//具體的裝飾類
class DecoratorPhoneA : public DecoratorPhone
{
public:
  DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}

  void ShowDecorate()
  {
    DecoratorPhone::ShowDecorate();
    AddDecorate();
  }

private:
  void AddDecorate() { cout << "更新為Plus" << endl; } //增加的裝飾
};

//具體的裝飾類
class DecoratorPhoneB : public DecoratorPhone
{
public:
  DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}

  void ShowDecorate()
  {
    DecoratorPhone::ShowDecorate(); 
    AddDecorate();
  }

private:
  void AddDecorate() { cout << "更新為6s" << endl; } //增加的裝飾
};

int main()
{
  Phone *iphone = new iPhone("iPhone6");
  Phone *plus = new DecoratorPhoneA(iphone); 

  Phone *s_6 = new DecoratorPhoneB(plus);    
  s_6->ShowDecorate();
  delete plus;
  delete s_6;
  delete iphone;
  return 0;
}      

繼續閱讀