前言
我們都知道,這個國際政治是一門很深的學問,不玩政治的人是搞不懂的。那么多的國家,國家之間的關系又及其復雜;就好比現在,美國和中國有經濟利益關系,美國又和日本有盟友關系,朝鮮又和中國有說不清道不明的關系;這些復雜的關系,稍微處理不好,就可能引發局部戰爭,更有可能引發第三次世界大戰。如果出現了國與國之間出現了利益糾紛,那么該怎么辦呢?這個時候,聯合國出現了。聯合國就是一個處理國與國之間糾紛的中介者。
中介者模式
在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對中介者模式是這樣說的:用一個中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。
我們都知道,面向對象設計鼓勵將行為分布到各個對象中。但是,這種分布可能會導致對象間有許多連接。在最壞的情況下,每一個對象都知道其他所有對象,就造成了復雜的關聯關系。雖然將一個系統分割成許多對象通??梢栽鰪娍蓮陀眯?,但是對象間相互連接的激增又會降低其可復用性。大量的相互連接使得一個對象似乎不太可能在沒有其他對象的支持下工作,這樣使得系統表現為一個不可分割的整體。而且,對系統的行為進行任何較大的改動都十分困難,因為行為被分布在許多對象中。結果是,你可能不得不定義很多子類以定制系統的行為。
問題再回到聯合國的問題上來,在聯合國還沒有成立時,國與國之間的關系是這樣的:

當聯合國成立以后,國與國之間出現糾紛時,是這樣的:

聯合國的成立,讓很多關系簡單化了,讓問題的處理也簡單化了,使國與國之間因為糾紛產生摩擦的幾率減小了,讓世界更和平了。
UML類圖

Mediator:中介者,它定義了一個接口用于與各個Colleague對象通信;
ConcreteMediator:具體的中介者,它通過協調各Colleague對象實現協作行為;并了解和維護它的各個Colleague;
Colleague:同事類,每一個同事類都知道它的中介者對象;每一個同時對象在需要與其他的同事通信的時候,而是與它的中介者通信。
它們之間是按照以下方式進行協作的:
同事向一個中介者對象發送和接收請求。中介者在各同事間適當地轉發請求以實現協作行為。
使用場合
在下列情況下使用中介者模式:
1.一組對象以定義良好但是復雜的方式進行通信。產生的相互依賴關系結構混亂且難以理解;
2.一個對象引用其他很多對象并且直接與這些對象通信,導致難以復用該對象;
3.想定制一個分布在多個類中的行為,而又不想生成太多的子類。
優缺點
1.減少了子類生成,Mediator將原本分布于多個對象間的行為集中在一起。改變這些行為只需生成Meditator的子類即可。這樣各個Colleague類可被重用;
2.它將各Colleague解耦,Mediator有利于各Colleague間的松耦合。你可以獨立的改變和復用各Colleague類和Mediator類;
3.它簡化了對象協議,用Mediator和Colleague間的一對多的交互來代替多對多的交互。一對多的關系更容易理解、維護和擴展;
4.它對對象如何協作進行了抽象,將中介作為一個獨立的概念并將其封裝在一個對象中,使你將注意力從對象各自本身的行為轉移到它們之間的交互上來。這有助于弄清楚一個系統中的對象是如何交互的;
5.它使控制集中化,中介者模式將交互的復雜性變為中介者的復雜性。因為中介者封裝了協議,它可能變得比任一個Colleague都復雜。這可能使得中介者自身成為一個難于維護的龐然大物。
代碼實現
實現一個通用的中介者模式:
#include <iostream>
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
class Mediator;
class Colleague
{
public:
Colleague(Mediator *pMediator) : m_pMediator(pMediator){}
virtual void Send(wchar_t *message) = 0;
protected:
Mediator *m_pMediator;
};
class ConcreteColleague1 : public Colleague
{
public:
ConcreteColleague1(Mediator *pMediator) : Colleague(pMediator){}
void Send(wchar_t *message);
void Notify(wchar_t *message)
{
wcout<<message<<endl;
}
};
class ConcreteColleague2 : public Colleague
{
public:
ConcreteColleague2(Mediator *pMediator) : Colleague(pMediator){}
void Send(wchar_t *message);
void Notify(wchar_t *message)
{
cout<<"ConcreteColleague2 is handling the message."<<endl;
wcout<<message<<endl;
}
};
class Mediator
{
public:
virtual void Sent(wchar_t *message, Colleague *pColleague) = 0;
};
class ConcreteMediator : public Mediator
{
public:
// The mediator forward the message
void Sent(wchar_t *message, Colleague *pColleague)
{
ConcreteColleague1 *pConcreteColleague1 = dynamic_cast<ConcreteColleague1 *>(pColleague);
if (pConcreteColleague1)
{
cout<<"The message is from ConcreteColleague1. Now mediator forward it to ConcreteColleague2"<<endl;
if (m_pColleague2)
{
m_pColleague2->Notify(message);
}
}
else
{
if (m_pColleague1)
{
m_pColleague1->Notify(message);
}
}
}
void SetColleague1(Colleague *pColleague)
{
m_pColleague1 = dynamic_cast<ConcreteColleague1 *>(pColleague);
}
void SetColleague2(Colleague *pColleague)
{
m_pColleague2 = dynamic_cast<ConcreteColleague2 *>(pColleague);
}
private:
// The Mediator knows all the Colleague
ConcreteColleague1 *m_pColleague1;
ConcreteColleague2 *m_pColleague2;
};
void ConcreteColleague1::Send(wchar_t *message)
{
// The second parameter mark where the message comes from
m_pMediator->Sent(message, this);
}
void ConcreteColleague2::Send(wchar_t *message)
{
m_pMediator->Sent(message, this);
}
int main()
{
// Create the mediator
Mediator *pMediator = new ConcreteMediator();
Colleague *pColleague1 = new ConcreteColleague1(pMediator);
Colleague *pColleague2 = new ConcreteColleague2(pMediator);
ConcreteMediator *pConcreteMediator = dynamic_cast<ConcreteMediator *>(pMediator);
pConcreteMediator->SetColleague1(pColleague1);
pConcreteMediator->SetColleague2(pColleague2);
wchar_t message[260] = L"Where are you from?";
pColleague1->Send(message);
return 0;
}
與外觀模式的區別
我在看中介者模式時,第一眼就感覺中介者模式和外觀模式超級像。外觀模式與中介者模式的不同之處在于它是對一個對象子系統進行抽象,從而提供了一個更為方便的接口;外觀模式的協議是單向的,即外觀模式向子系統提出請求,但反過來則不行;而對于中介者模式,是進行多個對象之間的協作,通信是多向的。
總結
中介者模式是一個比較簡單的設計模式,我在這里對中介者模式進行總結,希望對大家有用。這篇也是蛇年的最后一篇文章了。馬年見了,在這里提前祝愿大家馬年快樂。