在做面向對象的軟件開發時我們往往想達到更高的代碼可複用性和更合理的軟件顆粒度。
根據《設計模式——可複用面向對象軟件的基礎》所說:“你必須找到相關的對象,以適當的顆粒度將他們迴歸類,再定義類的接口和繼承層次,建立對象之間的基本關係。你的設計應該對手頭的問題有針對性,同時對將來的問題和需求也要有足夠的通用性。”
內行的設計者知道:不是解決任何問題都要從頭做起。他們更願意複用以前使用的解決方案。這些重複的模式方案解決特定的問題,使得面向對象的設計更靈活、優雅,最終複用性更好。它們幫助設計者將新的設計建立在以往的工作基礎上,複用以往的成功設計方案。一個熟悉這些設計模式的設計者不需要再去發現它們,而能夠立即將他們應用於設計問題中。
本系列文章主要參考文獻爲——設計模式,可複用面向對象軟件的基礎(Design Patterns Elements of Reusable Object-Oriented SoftWare Erich.),內部代碼基本用C++語言編寫。
文章目錄
摘要
本章主要說明中介者模式,該設計模式主要意圖是:用一箇中介對象來封裝對象之間的交互行爲。中介者使對象之間不用顯式的引用,降低類對象之間的耦合。
本篇文章以二手車交易爲例子,分別有寶馬、奔馳車賣家,寶馬、奔馳車買家四個對象存在,通過汽車交易中介進行消息交流,賣家告訴中介我要賣車,中介通知買家有人賣車。希望能通過這個簡單例子來說明白這種設計模式
主要參與者
該設計模式的參與者有6個,分別是:
- Mediator 抽象中介者
- ConcreteMediator 具體中介者
- Object 抽象對象
- ConcreteObject 具體對象
- Client 用戶
優點
對於該設計模式的優點大概說以下幾點,如有不同請提出寶貴意見:
- 對客戶影藏具體的產品類,減少客戶知道的名字和數量;(影藏的是產生的中間子類,客戶只知道有Prototype 不知道 PrototypeA的存在)
- 方便在運行時刻增加和刪除產品;
- 改變值以指定新的對象;
- 改變結構以指定新的對象;
- 減少子類的構造;
- 用類動態配置應用;
實施流程與具體實現
總體流程
- 實例中介者對象;
- 實例具體用戶;
- 用戶保存中介者對象指針;
- 用戶給中介發送通知消息;
具體實現代碼
接下來我們通過一個實例代碼來說明具體實現:
抽象中介者類(Mediator )
//抽象中介者類
class Mediator
{
public:
virtual void SetBMWCustomer(Person *person); //設置產品1買家
virtual void SetBenzCustomer(Person *person); //設置產品2買家
virtual void SetBMWSeller(Person *person); //設置產品1賣家
virtual void SetBenzSeller(Person *person); //設置產品2買家
virtual void SendMsg(string msg, Person *person);//消息傳遞接口
}
具體中介者(ConcreteMediator )
//具體中介者類
class ConcreteMediator2ndCarSalesShop: public Mediator
{
private:
//此處保存的指針可用數組來代替,這樣能實現單對多的對象交互
Person *m_BMWCustomer;
Person *m_BenzCustomer;
Person *m_BMWSeller;
Person *m_BenzSeller;
public:
void SetBMWCustomer(Person *person)
{
m_BMWCustomer = person;
}
void SetBenzCustomer(Person *person)
{
m_BenzCustomer = person;
}
void SetBMWSeller(Person *person)
{
m_BenzBMWSeller = person;
}
void SetBenzSeller(Person *person)
{
m_BenzBenzSeller = person;
}
void SendMsg(string msg, Person *person)
{
//若保存改爲數組,則該處可用數組遍歷來傳遞消息
if(person == m_BMWCustomer)
{
m_BMWSeller->GetMsg(msg);
}
else if(person == m_BenzCustomer)
{
m_BenzSeller->GetMsg(msg);
}
else if(person == m_BMWSeller)
{
m_BMWCustomer->GetMsg(msg);
}
else if(person == m_BenzSeller)
{
m_BMWCustomer->GetMsg(msg);
}
}
}
抽象對象(Object )
//抽象對象
class Person
{
public:
virtual void SendMsg(string msg);
virtual void GetMsg(string msg);
virtual void SetMediator(Mediator *mediator);
}
具體對象(ConcreteObject )
//具體對象寶馬車買家
class ConcreteBMWCustomer: public Person
{
private:
Meadiator *m_mediator;
public:
void SetMediator(Mediator *mediator)
{
m_mediator = mediator;
}
void SendMsg(string msg)
{
m_mediator->SendMsg(msg, this);
}
void GetMsg(string msg)
{
cout<<"BMWCustomer get mssage from CarSalesShop: "<<msg<<endl;
}
}
//具體對象奔馳車買家
class ConcreteBenzCustomer: public Person
{
private:
Meadiator *m_mediator;
public:
void SetMediator(Mediator *mediator)
{
m_mediator = mediator;
}
void SendMsg(string msg)
{
m_mediator->SendMsg(msg, this);
}
void GetMsg(string msg)
{
cout<<"BenzCustomer get mssage from CarSalesShop: "<<msg<<endl;
}
}
//具體對象寶馬車賣家
class ConcreteBMWSeller: public Person
{
private:
Meadiator *m_mediator;
public:
void SetMediator(Mediator *mediator)
{
m_mediator = mediator;
}
void SendMsg(string msg)
{
m_mediator->SendMsg(msg, this);
}
void GetMsg(string msg)
{
cout<<"BMWSeller get mssage from CarSalesShop: "<<msg<<endl;
}
}
//具體對象奔馳車賣家
class ConcreteBenzSeller: public Person
{
private:
Meadiator *m_mediator;
public:
void SetMediator(Mediator *mediator)
{
m_mediator = mediator;
}
void SendMsg(string msg)
{
m_mediator->SendMsg(msg, this);
}
void GetMsg(string msg)
{
cout<<"BenzSeller get mssage from CarSalesShop: "<<msg<<endl;
}
}
客戶(Client)
//客戶 client
int main()
{
Mediator *mediator = new ConcreteMediator2ndCarSalesShop();
Person *bmwSeller = new ConcreteBMWSeller();
Person *benzSeller = new ConcreteBenzSeller();
Person *bmwCustomer = new ConcreteBMWCustomer();
Person *benzCustomer = new ConcreteBenzCustomer();
bmwSeller->SetMediator(mediator);
benzSeller->SetMediator(mediator);
bmwCustomer->SetMediator(mediator);
benzCustomer->SetMediator(mediator);
bmwSeller->SendMsg("I want to sell my BMW520");
benzCustomer->SendMsg("I want to buy G500");
delete mediator; delete bmwSeller; delete benzSeller; delete bmwCustomer; delete benzCustomer;
return 0;
}
/*輸出
BMWCustomer get mssage from CarSalesShop: I want to sell my BMW520
BenzSeller get mssage from CarSalesShop: I want to buy G500
*/
補充說明
與現實中相同我們在生活中可能並沒有那麼多的時間去做數據管理以及篩選買家或買家,我們通常把這樣的工作都交給中介來完成,你可以預留下自己的需求,當中介遇到類似的需求時通知你,這樣大大減少了你的時間和精力花費。
我們何時使用該模式呢?可以按照上邊說的這個案例來分析是否類似,如果有類似的需求即可套用。
一組對象以定義良好但是複雜的方式進行通信。產生相互依賴關係結構混亂且難以理解。
一個對象引用其它很多對象並且直接與這些對象通信,導致難以複用該對象。
想定製一個分佈在多個類中的行爲,而又不想生成太多的子類。
——Gof 《 Design Pattern 》
本篇博客中的代碼爲純手寫未做編譯,如有Bug,請提出寶貴意見~