1、組合模式
組合模式的實現根據所實現接口的區別分為兩種形式,分別稱為安全模式和透明模式。組合模式可以不提供父對象的管理方法,但組合模式必須在合適的地方提供子對象的管理方法。
透明方式
作為第一種選擇,在Component里面聲明所有的用來管理子類對象的方法,包括add()、remove(),以及getChild()方法。這樣做的好處是所有的構件類都有相同的接口。在客戶端看來,樹葉類對象與合成類對象的區別起碼在接口層次上消失了,客戶端可以同等同的對待所有的對象。這就是透明形式的組合模式。
這個選擇的缺點是不夠安全,因為樹葉類對象和合成類對象在本質上是有區別的。樹葉類對象不可能有下一個層次的對象,因此add()、remove()以及getChild()方法沒有意義,是在編譯時期不會出錯,而只會在運行時期才會出錯或者說識別出來。
第二種選擇是在Composite類里面聲明所有的用來管理子類對象的方法。這樣的做法是安全的做法,因為樹葉類型的對象根本就沒有管理子類對象的方法,因此,如果客戶端對樹葉類對象使用這些方法時,程序會在編譯時期出錯。
這個選擇的缺點是不夠透明,因為樹葉類和合成類將具有不同的接口。
這兩個形式各有優缺點,需要根據軟件的具體情況做出取舍決定。
類圖結構及樣例實現:
這里給出安全方式的組合模式的類圖結構和樣例實現,透明方式就是在葉子節點的add()/remove()/GetChild()均有實現,不過是無意義的實現。大部分應用都是基于透明模式的,因為這樣代碼可以重用。
這種形式涉及到三個角色:
抽象構件(Component)角色:這是一個抽象角色,它給參加組合的對象定義出公共的接口及其默認行為,可以用來管理所有的子對象。在安全式的合成模式里,構件角色并不是定義出管理子對象的方法,這一定義由樹枝構件對象給出。
樹葉構件(Leaf)角色:樹葉對象是沒有下級子對象的對象,定義出參加組合的原始對象的行為。
樹枝構件(Composite)角色:代表參加組合的有下級子對象的對象。樹枝對象給出所有的管理子對象的方法,如add()、remove()、getChild()等。
2、職責鏈模式
職責鏈模式:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。其思想很簡單,考慮員工要求加薪。公司的管理者一共有三級,總經理、總監、經理,如果一個員工要求加薪,應該向主管的經理申請,如果加薪的數量在經理的職權內,那么經理可以直接批準,否則將申請上交給總監。總監的處理方式也一樣,總經理可以處理所有請求。這就是典型的職責鏈模式,請求的處理形成了一條鏈,直到有一個對象處理請求。
代碼如下:
/抽象管理者
classManager
{
protected:
Manager?*m_manager;
string?m_name;
public:
Manager(Manager?*manager,?string?name):m_manager(manager),?m_name(name){}
virtualvoidDealWithRequest(string?name,intnum)??{}
};
//經理
classCommonManager:publicManager
{
public:
CommonManager(Manager?*manager,?string?name):Manager(manager,name)?{}
voidDealWithRequest(string?name,intnum)
{
if(num?<?500)//經理職權之內
{
cout<<"經理"<
}
else
{
cout<<"經理"<
m_manager->DealWithRequest(name,?num);
}
}
};
//總監
classMajordomo:publicManager
{
public:
Majordomo(Manager?*manager,?string?name):Manager(manager,name)?{}
voidDealWithRequest(string?name,intnum)
{
if(num?<?1000)//總監職權之內
{
cout<<"總監"<
}
else
{
cout<<"總監"<
m_manager->DealWithRequest(name,?num);
}
}
};
//總經理
classGeneralManager:publicManager
{
public:
GeneralManager(Manager?*manager,?string?name):Manager(manager,name)?{}
voidDealWithRequest(string?name,intnum)//總經理可以處理所有請求
{
cout<<"總經理"<
}
};
客戶調用方式為:
[cpp]view plaincopy
//測試案例
intmain()
{
Manager?*general?=newGeneralManager(NULL,"A");//設置上級,總經理沒有上級
Manager?*majordomo?=newMajordomo(general,"B");//設置上級
Manager?*common?=newCommonManager(majordomo,"C");//設置上級
common->DealWithRequest("D",300);//員工D要求加薪
common->DealWithRequest("E",?600);
common->DealWithRequest("F",?1000);
deletecommon;deletemajordomo;deletegeneral;
return0;
}