设计模式之组合模式(Composite)摘录
23種GOF設計模式一般分為三大類:創建型模式、結構型模式、行為模式。
創建型模式抽象了實例化過程,它們幫助一個系統獨立于如何創建、組合和表示它的那些對象。一個類創建型模式使用繼承改變被實例化的類,而一個對象創建型模式將實例化委托給另一個對象。創建型模式有兩個不斷出現的主旋律。第一,它們都將關于該系統使用哪些具體的類的信息封裝起來。第二,它們隱藏了這些類的實例是如何被創建和放在一起的。整個系統關于這些對象所知道的是由抽象類所定義的接口。因此,創建型模式在什么被創建,誰創建它,它是怎樣被創建的,以及何時創建這些方面給予了很大的靈活性。它們允許用結構和功能差別很大的“產品”對象配置一個系統。配置可以是靜態的(即在編譯時指定),也可以是動態的(在運行時)。
結構型模式涉及到如何組合類和對象以獲得更大的結構。結構型類模式采用繼承機制來組合接口或實現。結構型對象模式不是對接口和實現進行組合,而是描述了如何對一些對象進行組合,從而實現新功能的一些方法。因為可以在運行時刻改變對象組合關系,所以對象組合方式具有更大的靈活性,而這種機制用靜態類組合是不可能實現的。
行為模式涉及到算法和對象間職責的分配。行為模式不僅描述對象或類的模式,還描述它們之間的通信模式。這些模式刻畫了在運行時難以跟蹤的復雜的控制流。它們將用戶的注意力從控制流轉移到對象間的聯系方式上來。行為類模式使用繼承機制在類間分派行為。行為對象模式使用對象復合而不是繼承。一些行為對象模式描述了一組對等的對象怎樣相互協作以完成其中任一個對象都無法單獨完成的任務。
創建型模式包括:1、FactoryMethod(工廠方法模式);2、Abstract Factory(抽象工廠模式);3、Singleton(單例模式);4、Builder(建造者模式、生成器模式);5、Prototype(原型模式).
結構型模式包括:6、Bridge(橋接模式);7、Adapter(適配器模式);8、Decorator(裝飾模式);9、Composite(組合模式);10、Flyweight(享元模式);11、Facade(外觀模式);12、Proxy(代理模式).
行為模式包括:13、TemplateMethod(模板方法模式);14、Strategy(策略模式);15、State(狀態模式);16、Observer(觀察者模式);17、Memento(備忘錄模式);18、Mediator(中介者模式);19、Command(命令模式);20、Visitor(訪問者模式);21、Chain of Responsibility(責任鏈模式);22、Iterator(迭代器模式);23、Interpreter(解釋器模式).
Factory Method:定義一個用于創建對象的接口,讓子類決定將哪一個類實例化。Factory Method使一個類的實例化延遲到其子類。
Abstract Factory:提供一個創建一系列相關或相互依賴對象的接口,而無需指定他們具體的類。
Singleton:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
Builder:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
Prototype:用原型實例指定創建對象的種類,并且通過拷貝這個原型來創建新的對象。
Bridge:將抽象部分與它的實現部分分離,使它們都可以獨立地變化。
Adapter:將一個類的接口轉換成客戶希望的另外一個接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。
Decorator:動態地給一個對象添加一些額外的職責。就擴展功能而言, Decorator模式比生成子類方式更為靈活。
Composite:將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得客戶對單個對象和復合對象的使用具有一致性。
Flyweight:運用共享技術有效地支持大量細粒度的對象。
Facade:為子系統中的一組接口提供一個一致的界面, Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
Proxy:為其他對象提供一個代理以控制對這個對象的訪問。
Template Method:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。Template Method使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
Strategy:定義一系列的算法,把它們一個個封裝起來, 并且使它們可相互替換。本模式使得算法的變化可獨立于使用它的客戶。
State:允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它所屬的類。
Observer:定義對象間的一種一對多的依賴關系,以便當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并自動刷新。
Memento:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這個狀態。這樣以后就可將該對象恢復到保存的狀態。
Mediator:用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。
Command:將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日志,以及支持可取消的操作。
Visitor:表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
Chain of Responsibility:為解除請求的發送者和接收者之間耦合,而使多個對象都有機會處理這個請求。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它。
Iterator:提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。
Interpreter:給定一個語言, 定義它的文法的一種表示,并定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
???????? Composite:(1)、意圖:將對象組合成樹形結構以表示“部分--整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。
???????? (2)、適用性:A、你想表示對象的部分--整體層次結構;B、你希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
???????? (3)、優缺點:A、定義了包含基本對象和組合對象的類層次結構:基本對象可以被組合成更復雜的組合對象,而這個組合對象又可以被組合,這樣不斷的遞歸下去。客戶代碼中,任何用到基本對象的地方都可以使用組合對象。B、簡化客戶代碼:客戶可以一致地使用組合結構和單個對象。通常用戶不知道(也不關心)處理的是一個葉節點還是一個組合組件。這就簡化了客戶代碼,因為在定義組合的那些類中不需要寫一些充斥著選擇語句的函數。C、使得更容易增加新類型的組件:新定義的Composite或Leaf子類自動地與已有的結構和客戶代碼一起工作,客戶程序不需要因新的Component類而改變。D、使你的設計變得更加一般化:有時你希望一個組合只能有某些特定的組件。使用Composite時,你不能依賴類型系統施加這些約束,而必須在運行時刻進行檢查。
???????? (4)、注意事項:A、顯示的父部件引用:保持從子部件到父部件的引用能簡化組合結構的遍歷和管理。父部件引用可以簡化結構的上移和組件的刪除,同時父部件引用也支持Chain of Responsibility。B、共享組件:共享組件是很有用的,比如它可以減少對存貯的需求。但是當一個組件只有一個父部件時,很難共享組件。C、最大化Component接口:Composite模式的目的之一是使得用戶不知道他們正在使用的具體的Leaf和Composite類。為了達到這一目的,Composite類應為Leaf和Composite類盡可能多定義一些公共操作。Composite類通常為這些操作提供缺省的實現,而Leaf和Composite子類可以對它們進行重定義。D、聲明管理子部件的操作。E、Component是否應該實現一個Component列表:你可能希望在Component類中將子節點集合定義為一個實例變量,而這個Component類中也聲明了一些操作對子節點進行訪問和管理。但是在基類中存放子類指針,對葉節點來說會導致空間浪費,因為葉節點根本沒有子節點。只有當該結構中子類數目相對較少時,才值得使用這種方法。F、子部件排序:如果需要考慮子節點的順序時,必須仔細地設計對子節點的訪問和管理接口,以便管理子節點序列。Iterator模式可以在這方面給予一些指導。G、使用高速緩沖存貯改善性能:如果你需要對組合進行頻繁的遍歷或查找,Composite類可以緩沖存儲對它的子節點進行遍歷或查找相關信息。H、應該由誰刪除Component:在沒有垃圾回收機制的語言中,當一個Composite被銷毀時,通常最好由Composite負責刪除其子節點。但有一種情況除外,即Leaf對象不會改變,因此可以被共享。I、存貯組件最好用哪一種數據結構:Composite可使用多種數據結構存貯它們的子節點,包括連接列表、樹、數組和hash表。數據結構的選擇取決于效率。事實上,使用通用數據結構根本沒有必要。有時對每個子節點,Composite都有一個變量與之對應,這就要求Composite的每個子類都要實現自己的管理接口。
???????? (5)、相關模式:A、通常部件----父部件連接用于Responsibilityof Chain模式。B、Decorator模式經常與Composite模式一起使用。當裝飾和組合一起使用時,它們通常有一個公共的父類。因此裝飾必須支持具有Add、Remove和GetChild操作的Component接口。C、Flyweight讓你共享組件,但不再能引用他們的父部件。D、Iterator可用來遍歷Composite. E、Visitor將本來應該分布在Composite和Leaf類中的操作和行為局部化。
???????? Composite模式在實現中有一個問題就是要提供對于子節點(Leaf)的管理策略,可以提供的實現方式有:vector、數組、鏈表、Hash表等。
???????? Composite模式通過和Decorator模式有著類似的結構圖,但是Composite模式旨在構造類,而Decorator模式重在不生成子類即可給對象添加職責。Decorator模式重在修飾,而Composite模式重在表示。
示例代碼1:
#include <iostream>
#include <string>
#include <vector>using namespace std;class Component
{
public:string m_strName;Component(string strName){m_strName = strName;}virtual void Add(Component* com) = 0;virtual void Display(int nDepth) = 0;
};class Leaf : public Component
{
public:Leaf(string strName) : Component(strName) {}virtual void Add(Component* com){cout<<"leaf can't add"<<endl;}virtual void Display(int nDepth){string strtemp;for (int i = 0; i < nDepth; i ++)strtemp += "-";strtemp += m_strName;cout<<strtemp<<endl;}
};class Composite : public Component
{
private:vector<Component*> m_component;
public:Composite(string strName) : Component(strName) {}virtual void Add(Component* com){m_component.push_back(com);}virtual void Display(int nDepth){string strtemp;for (int i = 0; i < nDepth; i ++)strtemp += "-";strtemp += m_strName;cout<<strtemp<<endl;vector<Component*>::iterator p = m_component.begin();while (p != m_component.end()) {(*p)->Display(nDepth + 2);p ++;}}
};//客戶端
int main()
{Composite* p = new Composite("小王");p->Add(new Leaf("小李"));p->Add(new Leaf("小趙"));Composite* p1 = new Composite("小小五");p1->Add(new Leaf("大三"));p->Add(p1);p->Display(1);/*result-小王---小李---小趙---小小五-----大三*/return 0;
}
示例代碼2:
#include <iostream>
#include <string>
#include <vector>using namespace std;class Company
{
protected:string m_strName;
public:Company(string strName){m_strName = strName;}virtual void Add(Company* c) = 0;virtual void Display(int nDepth) = 0;virtual void LineOfDuty() = 0;
};class ConcreteCompany : public Company
{
private:vector<Company*> m_company;
public:ConcreteCompany(string strName) : Company(strName) {}virtual void Add(Company* c){m_company.push_back(c);}virtual void Display(int nDepth){string strtemp;for (int i = 0; i < nDepth; i ++)strtemp += "-";strtemp += m_strName;cout<<strtemp<<endl;vector<Company*>::iterator p = m_company.begin();while (p != m_company.end()) {(*p)->Display(nDepth + 1);p ++;}}virtual void LineOfDuty(){vector<Company*>::iterator p = m_company.begin();while (p != m_company.end()) {(*p)->LineOfDuty();p ++;}}
};class HrDepartment : public Company
{
public:HrDepartment(string strname) : Company(strname) {}virtual void Display(int nDepth){string strtemp;for (int i = 0; i < nDepth; i ++)strtemp += "-";strtemp += m_strName;cout<<strtemp<<endl;}virtual void Add(Company* c){cout<<"error"<<endl;}virtual void LineOfDuty(){cout<<m_strName<<":招聘人才"<<endl;}
};//客戶端
int main()
{ConcreteCompany* p = new ConcreteCompany("清華大學");p->Add(new HrDepartment("清華大學人才部"));ConcreteCompany* p1 = new ConcreteCompany("數學系");;p1->Add(new HrDepartment("數學系人才部"));ConcreteCompany* p2 = new ConcreteCompany("物理系");p2->Add(new HrDepartment("物理系人才部"));p->Add(p1);p->Add(p2);p->Display(1);p->LineOfDuty();/*result-清華大學--清華大學人才部--數學系---數學系人才部--物理系---物理系人才部清華大學人才部:招聘人才數學系人才部:招聘人才物理系人才部:招聘人才*/return 0;
}
示例代碼3:
Component.h:
#ifndef _COMPONENT_H_
#define _COMPONENT_H_class Component
{
public:Component();virtual ~Component();
public:virtual void Operation() = 0;virtual void Add(const Component&);virtual void Remove(const Component&);virtual Component* GetChild(int);
protected:
private:
};#endif//~_COMPONENT_H_
Component.cpp:
#include "Component.h"Component::Component()
{}Component::~Component()
{}void Component::Add(const Component&)
{}Component* Component::GetChild(int index)
{return 0;
}void Component::Remove(const Component& com)
{}
Composite.h:
#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_#include "Component.h"
#include <vector>using namespace std;class Composite : public Component
{
public:Composite();~Composite();
public:void Operation();void Add(Component* com);void Remove(Component* com);Component* GetChild(int index);
protected:
private:vector<Component*> comVec;
};#endif//~_COMPOSITE_H_
Composite.cpp:
#include "Composite.h"
#include "Component.h"#define NULL 0 //define NULL POINTORComposite::Composite()
{//vector<Component*>::iterator itend = comVec.begin();
}Composite::~Composite()
{}void Composite::Operation()
{vector<Component*>::iterator comIter = comVec.begin();for (; comIter != comVec.end(); comIter ++)(*comIter)->Operation();
}void Composite::Add(Component* com)
{comVec.push_back(com);
}void Composite::Remove(Component* com)
{//comVec.erase(&com);
}Component* Composite::GetChild(int index)
{return comVec[index];
}
Leaf.h:
#ifndef _LEAF_H_
#define _LEAF_H_#include "Component.h"class Leaf : public Component
{
public:Leaf();~Leaf();void Operation();
protected:
private:
};#endif //~_LEAF_H_
#include "Leaf.h"
#include <iostream>using namespace std;Leaf::Leaf()
{}Leaf::~Leaf()
{}void Leaf::Operation()
{cout<<"Leaf Operation ..."<<endl;
}
main.cpp:
#include "Component.h"
#include "Composite.h"
#include "Leaf.h"
#include <iostream>using namespace std;int main()
{Leaf* l = new Leaf();l->Operation();Composite* com = new Composite();com->Add(l);com->Operation();Component* ll = com->GetChild(0);ll->Operation();/*resultLeaf Operation ...Leaf Operation ...Leaf Operation ...*/return 0;
}
組合模式結構圖:
參考文獻:
1、《大話設計模式C++》
2、《設計模式精解----GoF23種設計模式解析》
3、《設計模式----可復用面向對象軟件的基礎》
總結
以上是生活随笔為你收集整理的设计模式之组合模式(Composite)摘录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式之装饰模式(Decorator)
- 下一篇: 设计模式之享元模式(Flyweight)