爲方便讀者,本文已添加至索引:html
在Composite(組合)模式中,用戶可使用多個簡單的組件以造成較大的組件,而這些組件還可能進一步組合成更大的。它重要的特性是可以讓用戶一致地對待單個對象和組合對象。不知你們是否還記得女巫格琳達(見筆記Facade模式),她的小屋經營得很順利,給小夥伴們的生活帶來了極大地便利。今天,她又推出了一項全新的銷售項目,那就是「私人訂製自主行動型魔法小人偶-I」。乍看之下是個稻草人模樣,但其實客人們可以經過本身訂製小人偶的不一樣部件,組裝成一個能夠按照預先設定的指望目標而自主行動的魔法人偶。他們能夠幫忙播種,耕地,烹飪,甚至戰鬥等等等等。設計模式
女巫格琳達在設計這個小人偶原型時,採用了Composite模式從而簡化了客戶們的操做,同時也能利用清晰的樹形結構來展現訂製的所有內容。在咱們進入到示例部分講解小人偶相關代碼以前,先來具體瞭解下Composite模式的基本知識:函數
從上文的UML圖中,能夠看到Composite模式描述瞭如何使用遞歸組合,使得用戶沒必要對單個類與組合類進行區別。而實現這一點的關鍵,在於Component抽象類,它既能表明單個組件,又能表明容器。工具
對於咱們的魔法小人偶-I型而言,咱們一樣定義一個Component類爲接下來全部的部件定義一個接口。性能
1 class Component { 2 public: 3 virtual ~Component(); 4 5 const char* name() { return _name; } 6 7 virtual int myFunction(); // power on the function of the component. 8 virtual int myValue(); // count the value of the component. 9 10 virtual void add(Component*); 11 virtual void remove(Component*); 12 virtual Iterator<Component*>* createIterator(); 13 14 protected: 15 Component(const char*); 16 17 private: 18 const char* _name; 19 };
咱們看到Component聲明瞭一些操做來返回一個部件的屬性,譬如說它的價格等。子類將爲指定的部件實現這些接口。而對於createIterator操做,它可以返回一個訪問它零件的Iterator,從而可以在管理零件的時候,進行遍歷。學習
Component類的子類有不少,咱們將不會所有講述(那會顯得很冗餘)。咱們首先看到的是Leaf型的組件,它們不是容器,好比裝在原型裏面的驅動裝置,穿在外面的衣服,戴在頭上的帽子,可使用的武器、工具等等。好比咱們Clothes類:spa
1 class Clothes : public Component { 2 public: 3 Clothes(const char*); 4 virtual ~Clothes(); 5 6 virtual int myFunction(); 7 virtual int myValue(); 8 };
另外一些是Composite型的組件,它們做爲容器可以包含其餘部件。這種組件的基類CompositeComponent:設計
1 class CompositeComponent : public Component { 2 virtual ~CompositeComponent(); 3 4 virtual int myFunction(); 5 virtual int myValue(); 6 7 virtual void add(Component*); 8 virtual void remove(Component*); 9 virtual Iterator<Component*>* createIterator(); 10 11 protected: 12 CompositeComponent(const char*); 13 14 private: 15 List<Component*> _component; 16 };
它爲訪問和管理子部件定義了一些操做。操做add/remove將從存儲在_component成員變量中的部件列表中插入/刪除部件。而做爲容器的myValue操做,經過使用createIterator,來累加子部件的價格。code
1 int CompositeComponent::myValue() { 2 Iterator<Component*>* iter = createIterator(); 3 int total = 0; 4 for (iter->first(); !iter->isDone(); iter->next()) { 5 total += iter->current()->myValue(); 6 } 7 delete iter; 8 return total; 9 }
CompositeComponent類的子類之一ProtoBody,是最基本的人偶外殼容器,格琳達能夠經過在裏面安置一些驅動器Drive,傳感器Sensor等來使得它得以正常運做。component
1 class ProtoBody : public CompositeComponent { 2 public: 3 ProtoBody(const char*); 4 virtual ~ProtoBody(); 5 6 virtual int myFunction(); 7 virtual int myValue(); 8 };
好啦,咱們還能夠定義一些類似的其餘容器,譬如戰鬥人偶的武器袋WeaponBag等等。咱們能夠簡單地來模擬訂製一個可以保衛領土的戰鬥機器人:
1 ProtoBody* body = new ProtoBody("A strong and tough body"); 2 3 WeaponBag* bag = new WeaponBag("Weapon bag"); 4 bag->add(new Weapon("Sharpen Sword")); 5 bag->add(new Shield("Hard Shield")); 6 7 body->add(bag); 8 body->add(new Drive("Fight For Honor!")); 9 body->add(new Clothes("Cool Armor")); 10 11 cout << "The total price is " << body->myValue() << endl;
對於咱們的設計能夠看下面這張圖:
從上面咱們能夠看到,Composite模式有以下一些特色:
同時,咱們在實現的時候須要注意如下幾點:
今天的筆記就到這裏了,歡迎你們批評指正!若是以爲能夠的話,好文推薦一下,我會很是感謝的!