1. 程式人生 > 實用技巧 >裝飾模式(Decorator)C++實現

裝飾模式(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 }

部分結果:

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