裝飾模式
層層包裝,增強功能。這就是裝飾模式的要旨!裝飾器模式就是基於對象組合的方式,可以很靈活的給對象添加所需要的功能。它把需要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象。
意圖:
動態的給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類模式更為靈活。
適用性:
1、在不影響其它對象的情況下,以動態、透明的方式給單個對象添加職責。
2、處理那些可以撤銷的職責。
3、希望為某個對象而不是一整個類添加一些功能時。
4、當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。
效果:
1、比靜態繼承更為靈活。繼承機制會產生許多新類,增加了系統的復雜度。而裝飾可以使你對一些職責進行混合和匹配。
2、避免在層次結構高層的類有太多的特征。擴展一個復雜類的時候,很可能會暴露出與添加職責無關的細節。你可以定義一個簡單的類,並且用裝飾逐漸的添加功能。
3、會產生許多小對象。
4、Decorator與Component不一樣,Decorator是一個透明的包裝。如果我們從對象標識的觀點出發,一個被裝飾了的組件與這個組件是有差別的,因此,使用裝飾時不應該依賴對象標識。
注意:
1、接口的一致性。裝飾對象的接口必須與它所裝飾的Component的接口是一致的。
2、省略抽象的Docorator類。當你僅需要添加一個職責的時,沒有必要定義抽象Decorator類。你常常需要處理顯存的類層次結構而不是設計一個新系統,這時你可以把Decorator向Component轉發請求的職責合並到ConcreteDecorator中。
3、保持Component類的簡單性。為了保證接口的一致性,組件和裝飾必須有一個共同的Component父類。因此保持這個類的簡單些是很重要的。
參與者:
Component
——定義一個對象接口,可以給這些對象動態的添加職責。
ConcreteComponent
——定義一個對象,可以給這個對象添加一些職責。
Decorator
——維持一個指向Component對象的指針,並定義一個與Component接口一致的接口。
ConcreteDecorator
——向組件添加職責。
UML:

代碼實現:在控制台打印如下表格,基本的姓名、年齡、學歷、性別必須擁有,其它如英語等級等屬性自由添加。

打印一行表格代碼:
void print(char* str) { cout<<"├───────────────────────────────"<<endl <<"│"<<str<<":"<<endl; }
定義一個抽象基類absTable(Component)
class absTable { public: virtual void putTable() = 0; };
定義具體的表格absTable(ConcreteComponent)
class BaseTable:public absTable { public: virtual void putTable() { print("姓名"); print("性別"); print("學歷"); print("年齡"); cout<<"└───────────────────────────────"<<endl; } };
定義抽象Decorator
class Decorator:public absTable { public: Decorator(absTable* concrateTb):mpAbsTable(concrateTb){} virtual void putTable() { mpAbsTable->putTable(); } private: absTable* mpAbsTable; };
定義具體的裝飾EnglishDcrt、CurWage、Experience(ConcreteDecoratorA、B、C)
class EnglishDcrt:public Decorator { public: EnglishDcrt(absTable* pTb):Decorator(pTb){} virtual void putTable() { print("英語等級"); Decorator::putTable(); } };
class CurWage:public Decorator { public: CurWage(absTable* pTb):Decorator(pTb){} virtual void putTable() { print("當前薪水"); Decorator::putTable(); } };
class Experience:public Decorator { public: Experience(absTable* pTb):Decorator(pTb){} virtual void putTable() { print("項目經驗"); Decorator::putTable(); } };
客戶端代碼:
#include <iostream> #include "Decorator.h" using namespace std; //動態的給一個對象添加一些額外的職責! //層層包裝,增強功能。這就是裝飾模式的要旨! //接口穩定不變! void main() { BaseTable pro1; cout<<"初始表格:"<<endl<<endl; pro1.putTable(); cout<<"新表格1:"<<endl<<endl; EnglishDcrt eng(&pro1); eng.putTable(); cout<<"新表格2:"<<endl<<endl; CurWage wg(&eng); wg.putTable(); cout<<"新表格3:"<<endl<<endl; Experience ex(&wg); ex.putTable(); }
部分結果:

這樣我們實現了項目經驗、當前薪水、英語等級的自由組合,當然還可以添加更多的屬性。
