組合模式,將對象組合成樹形結構以表示「部分-總體」的層次結構,組合模式使得用戶對單個對象和組合對象的使用具備一致性。ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ ——Erich Gamma et. al.
組合(Composite)模式,又叫做部分-總體模式,它是一種將對象組合成樹狀的層次結構的模式,用來表示「部分-總體」的關係,使用戶對單個對象和組合對象具備一致的訪問性。ide
■ Component:抽象的組件對象,爲組合中的對象聲明接口,讓客戶端能夠經過這個接口來訪問和管理整個對象結構,能夠在裏面爲定義的功能提供缺省的實現。
■ Leaf:葉子節點對象,定義和實現葉子對象的行爲,再也不包含其餘的子節點對象。
■ Composite:組合對象,一般會存儲子組件,定義包含子組件的那些組件的行爲,並實如今組件接口中定義的與子組件有關的操做。
■ Client:客戶端,經過組件接口來操做組合結構裏面的組件對象。函數
Component
定義struct Component { virtual ~Component(){} ABSTRACT(void process()); virtual void add(Component*) { return; } virtual void remove(Component*) { return; } };
注意,上面ABSTRACT
是一個C++封裝宏,表示定義的方法是純虛函數,亦即接口,原型以下:學習
#define ABSTRACT(...) virtual __VA_ARGS__ = 0
因爲葉子對象沒有add
和remove
方法的,這裏在抽象類提供了一份默認實現。spa
Leaf
定義struct Leaf : Component { OVERRIDE(void process()) { /* do process self */ } };
其中,上面OVERRIDE
也是一個C++封裝宏,表示實現或者覆寫父類的接口(或方法),原型以下:設計
#define OVERRIDE(...) virtual __VA_ARGS__ override
Composite
定義using Components = std::list<Component*>; struct Composite : Component { explicit Composite(const std::string& name) : name_{name} {} OVERRIDE(void process()) { /* do process self */ /* process child */ for (auto& c : components_) { c->process(); } } OVERRIDE(void add(Component* component)) { components_.push_back(component) } OVERRIDE(void remove(Component* component)) { components_.remove(component) } private: std::string name_; Components components_; };
這裏假設用戶須要設計一個管理商品類別樹的場景,以下code
- 商品 - 服裝 - 男裝 - 女裝 - 書籍 - 中文書籍 - 外文書籍
使用組合模式,以下component
void process(Component& component) { component.process(); } int main() { Composite root("商品"); Composite dress("服裝"); Composite book("書籍"); Leaf man_dress("男裝"); Leaf women_dress("女裝"); Leaf book_zh("中文書籍"); Leaf book_foreign("外文書籍"); root.add(&dress); dress.add(&man_dress); dress.add(&women_dress); root.add(&book); book.add(&book_zh); book.add(&book_foreign); process(root); }
1. 定義了包含基本對象和組合對象的類層次結構,基本對象能夠被組合成複雜的組合對象,而組合對象又能夠組合成更復雜的組合對象,能夠不斷地遞歸組合下去,從而構成一個統一的組合對象的類層次結構。
2. 組合模式使得客戶端代碼能夠一致地處理單個對象和組合對象,無須關心本身處理的是單個對象,仍是組合對象,這簡化了客戶端代碼;
3. 更容易在組合體內加入新的對象,客戶端不會由於加入了新的對象而更改源代碼,知足「開閉原則」;對象
1. 不容易限制容器中的構件;
2. 不容易用繼承的方法來增長構件的新功能;blog
學習是輸入,分享是輸出,堅持持續分享。。。繼承