程序設計模式(九) C++ 裝飾(Decorator)模式

2.4  Decorator

裝飾模式提供了更加靈活的向對象添加職責的方式。可以用添加和分離的方法,用裝飾在運行時刻增加和刪除職責。裝飾模式提供了

一種“即用即付”的方法來添加職責。它並不試圖在一個複雜的可定製的類中支持所有可預見的特徵,相反,你可以定義一個簡單的

類,並且用裝飾類給它逐漸地添加功能。可以從簡單的部件組合出複雜的功能。

裝飾器模式就是基於對象組合的方式,可以很靈活的給對象添加所需要的功能。它把需要裝飾的功能放在單獨的類中,並讓這個類包

裝它所要裝飾的對象,動態的給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類模式更爲靈活。


思想:爲一個對象已有的子類添加一些額外的職責,具有以下優點:

       1、比靜態繼承更爲靈活。繼承機制會產生許多新類,增加了系統的複雜度。而裝飾可以使你對一些職責進行混合和匹配。

       2、避免在層次結構高層的類有太多的特徵。擴展一個複雜類的時候,很可能會暴露出與添加職責無關的細節。你可以定義一個

簡單的類,並且用裝飾逐漸的添加功能。

       3、會產生許多小對象

       4、Decorator與Component不一樣,Decorator是一個透明的包裝。如果我們從對象標識的觀點出發,一個被裝飾了的組件與這

個組件是有差別的,因此,使用裝飾時不應該依賴對象標識。


場景:該模式的使用場景,主要是有的時候我們不願意定義邏輯上新的子類,因爲沒有新的邏輯含義上的子類概念,而只是想爲一

個已存在的子類附加一些職責。

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

       2、處理那些可以撤銷的職責。

       3、希望爲某個對象而不是一整個類添加一些功能時。

       4、當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得

子類數呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。


實現:該模式的實現主要就是定義一個物理上的新的子類,但是,它只是包含要附加職責的類,傳遞外部對相同接口的調用,在這

個傳遞調用的通道上附加額外的功能。使用時注意:

       1、接口的一致性。裝飾對象的接口必須與它所裝飾的Component的接口是一致的。

       2、省略抽象的Docorator類。當你僅需要添加一個職責的時,沒有必要定義抽象Decorator類。你常常需要處理顯存的類層次結

構而不是設計一個新系統,這時你可以把Decorator向Component轉發請求的職責合併到ConcreteDecorator中。

       3、保持Component類的簡單性。爲了保證接口的一致性,組件和裝飾必須有一個共同的Component父類。因此保持這個類的簡

單些是很重要的。

實例:

  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class Component  
  5. {  
  6. public:  
  7.     virtual void Operation() = 0;  
  8. };  
  9.   
  10. class concreteComponent :public Component  
  11. {  
  12. public:  
  13.     void Operation()  
  14.     {  
  15.         cout << "this is a concreteComponent, not a decorator." << endl;  
  16.     }  
  17. };  
  18.   
  19. class Decorator :public Component  
  20. {  
  21. public:  
  22.     Decorator(Component *p) : p_Component(p) {}  
  23.     void Operation()  
  24.     {  
  25.         if (p_Component != NULL)  
  26.         {  
  27.             p_Component->Operation();  
  28.         }  
  29.     }  
  30.   
  31. private:  
  32.     Component *p_Component;  
  33. };  
  34.   
  35. class DecoratorA :public Decorator  
  36. {  
  37. public:  
  38.     DecoratorA(Component *p) : Decorator(p) {}  
  39.     void Operation()  
  40.     {  
  41.         add_status();  
  42.         Decorator::Operation();  
  43.     }  
  44.   
  45.     void add_status()  
  46.     {  
  47.         cout << "I am DecoratorA. " << endl;  
  48.     }  
  49. };  
  50.   
  51. class DecoratorB :public Decorator  
  52. {  
  53. public:  
  54.     DecoratorB(Component *p) : Decorator(p) {}  
  55.     void Operation()  
  56.     {  
  57.         add_bahavior();  
  58.         Decorator::Operation();  
  59.     }  
  60.   
  61.     void add_bahavior()  
  62.     {  
  63.         cout << "I am DecoratorB. " << endl;  
  64.     }  
  65. };  
  66.   
  67. int main(int argc, char*argv[])  
  68. {  
  69.     Component* object = new concreteComponent();  
  70.     Decorator *a = new DecoratorA(object);  
  71.     a->Operation();  
  72.     cout << "-----------------------------------------------------" << endl;  
  73.   
  74.     Decorator *b = new DecoratorB(object);  
  75.     b->Operation();  
  76.     cout << "------------------------------------------------------" << endl;  
  77.   
  78.     Decorator *ab = new DecoratorB(a);  
  79.     ab->Operation();  
  80. }  

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

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

                                                 

  1. #include <iostream>  
  2. #include <string>  
  3. using namespace std;  
  4.   
  5. //公共抽象類  
  6. class Phone  
  7. {  
  8. public:  
  9.     virtual void ShowDecorate() {}  
  10. };  
  11.   
  12. //具體的手機類  
  13. class iPhone : public Phone  
  14. {  
  15. public:  
  16.     iPhone(string s) :name(s){}  
  17.   
  18.     void ShowDecorate()  
  19.     {  
  20.         cout << "I am " << name << endl;  
  21.     }  
  22.   
  23. private:  
  24.     string name;//手機名  
  25. };  
  26.   
  27. //裝飾類  
  28. class DecoratorPhone : public Phone  
  29. {  
  30. private:  
  31.     Phone *m_phone;  //要裝飾的手機  
  32.   
  33. public:  
  34.     DecoratorPhone(Phone *phone) : m_phone(phone) {}  
  35.   
  36.     virtual void ShowDecorate() { m_phone->ShowDecorate(); }  
  37. };  
  38. //具體的裝飾類  
  39. class DecoratorPhoneA : public DecoratorPhone  
  40. {  
  41. public:  
  42.     DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}  
  43.   
  44.     void ShowDecorate()  
  45.     {  
  46.         DecoratorPhone::ShowDecorate();  
  47.         AddDecorate();  
  48.     }  
  49.   
  50. private:  
  51.     void AddDecorate() { cout << "升級爲Plus" << endl; } //增加的裝飾  
  52. };  
  53.   
  54. //具體的裝飾類  
  55. class DecoratorPhoneB : public DecoratorPhone  
  56. {  
  57. public:  
  58.     DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}  
  59.   
  60.     void ShowDecorate()  
  61.     {  
  62.         DecoratorPhone::ShowDecorate();   
  63.         AddDecorate();  
  64.     }  
  65.   
  66. private:  
  67.     void AddDecorate() { cout << "升級爲6s" << endl; } //增加的裝飾  
  68. };  
  69.   
  70. int main()  
  71. {  
  72.     Phone *iphone = new iPhone("iPhone6");  
  73.     Phone *plus = new DecoratorPhoneA(iphone);   
  74.   
  75.     Phone *s_6 = new DecoratorPhoneB(plus);      
  76.     s_6->ShowDecorate();  
  77.     delete plus;  
  78.     delete s_6;  
  79.     delete iphone;  
  80.     return 0;  
  81. }
重構成本:低。定義一個Decorator和一個已有類的邏輯上的子類,物理表現形式上都是一個子類,重構也確實不是難事。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章