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父類。因此保持這個類的簡
單些是很重要的。
實例:
- #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;
- }