裝飾模式(Decorator)C++實現
裝飾模式
層層包裝,增強功能。這就是裝飾模式的要旨!裝飾器模式就是基於物件組合的方式,可以很靈活的給物件新增所需要的功能。它把需要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的物件。
意圖:
動態的給一個物件新增一些額外的職責。就增加功能來說,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:
程式碼實現:在控制檯列印如下表格,基本的姓名、年齡、學歷、性別必須擁有,其它如英語等級等屬性自由新增。
列印一行表格程式碼:
1 void print(char* str)
2 {
3 cout<<"├───────────────────────────────"<<endl
4 <<"│"<<str<<":"<<endl;
5 }
定義一個抽象基類absTable(Component)
1 class absTable
2 {
3 public:
4 virtual void putTable() = 0;
5 };
定義具體的表格absTable(ConcreteComponent)
1 class BaseTable:public absTable
2 {
3 public:
4 virtual void putTable()
5 {
6 print("姓名");
7 print("性別");
8 print("學歷");
9 print("年齡");
10 cout<<"└───────────────────────────────"<<endl;
11 }
12 };
定義抽象Decorator
1 class Decorator:public absTable
2 {
3 public:
4 Decorator(absTable* concrateTb):mpAbsTable(concrateTb){}
5
6 virtual void putTable()
7 {
8 mpAbsTable->putTable();
9 }
10 private:
11 absTable* mpAbsTable;
12 };
定義具體的裝飾EnglishDcrt、CurWage、Experience(ConcreteDecoratorA、B、C)
1 class EnglishDcrt:public Decorator
2 {
3 public:
4 EnglishDcrt(absTable* pTb):Decorator(pTb){}
5
6 virtual void putTable()
7 {
8 print("英語等級");
9 Decorator::putTable();
10 }
11 };
1 class CurWage:public Decorator
2 {
3 public:
4 CurWage(absTable* pTb):Decorator(pTb){}
5
6 virtual void putTable()
7 {
8 print("當前薪水");
9 Decorator::putTable();
10 }
11 };
1 class Experience:public Decorator
2 {
3 public:
4 Experience(absTable* pTb):Decorator(pTb){}
5
6 virtual void putTable()
7 {
8 print("專案經驗");
9 Decorator::putTable();
10 }
11 };
客戶端程式碼:
1 #include <iostream>
2 #include "Decorator.h"
3
4 using namespace std;
5
6 //動態的給一個物件新增一些額外的職責!
7 //層層包裝,增強功能。這就是裝飾模式的要旨!
8 //介面穩定不變!
9
10 void main()
11 {
12 BaseTable pro1;
13 cout<<"初始表格:"<<endl<<endl;
14 pro1.putTable();
15
16 cout<<"新表格1:"<<endl<<endl;
17 EnglishDcrt eng(&pro1);
18 eng.putTable();
19
20 cout<<"新表格2:"<<endl<<endl;
21 CurWage wg(&eng);
22 wg.putTable();
23
24 cout<<"新表格3:"<<endl<<endl;
25 Experience ex(&wg);
26 ex.putTable();
27 }
部分結果:
這樣我們實現了專案經驗、當前薪水、英語等級的自由組合,當然還可以新增更多的屬性。