大話設計模式 —— 第二十五章《中介者模式》C++ 代碼實現

目錄

定義

優點

缺點

應用場景

代理模式、外觀模式和中介者模式對比


在現實生活中,常常會出現好多對象之間存在複雜的交互關係,這種交互關係常常是“網狀結構”,它要求每個對象都必須知道它需要交互的對象。 

 我想到了生活中的中介。有人有房子想出租(房東),但是他不想自己去找那些想租房子的人(租客),也不想保存那些想租房子的人的信息。而有些人想租房子(租客),但不知道哪些房源出租,也不想自己存房源的信息。那上面這兩類人怎麼辦呢?他們可以找中介。這就變成了 房東-中介-租客 之間的關係。這樣一來房東就不需要有租客的信息,也能將房子租出去,而租客也不需要房東的信息,也能找到房子,中介成了房東和租客之間的紐帶。而中介其實什麼都沒有,他的職能就是爲房東們尋找合適的租客,替租客們匹配合適的房子。

不通過中介
通過中介

   好的,我們通過中介的存在,切斷了房東與租客之間的聯繫,從而解決了房東和租客們的難題。這樣剛好符合設計模式中的迪米特原則,這個原則所說的就是要儘量減少對象之間的交互,如果兩個對象之間不必彼此直接通信,那麼這兩個對象就不應當發生任何直接的相互作用,如果其中的一個對象需要調用另一個對象的某一個方法的話,可以通過第三者轉發這個調用。  我們爲了減少對象之間的交互和耦合,符合迪米特原則,那麼就可以使用中介者模式,先來學習下中介者模式的定義。


定義


中介者模式(調停者模式,屬於行爲型設計模式):

  • 用一箇中介對象來封裝一系列的對象交互。中介者使各對象不需要顯示地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。

  • 抽象中介者(Mediator)角色:定義了同事對象到中介者對象的接口,提供了同事對象註冊與發送同事對象信息的抽象方法。主要用於各個同事對象之間的通信。
  • 具體中介者(ConcreteMediator)角色:繼承於抽象中介者,實現了父類定義的方法。具體中介者需要包含所有具體同事的引用,並通過實現中介者接口中的方法來滿足具體同事之間的通信請求。
  • 抽象同事類(Colleague)角色:保存了中介者對象引用,只與中介者交互,不與其他同時對象交互
  • 具體同事類(Concrete Colleague)角色:是抽象同事類的實現者,當需要與其他同事對象交互時,由中介者對象負責後續的交互。

這裏說的同事類就像我們前面所述的 租客,

下面用C++ 代碼實現大話設計模式本章代碼:

class UnitedNations;

//Colleague 類
class Country
{
protected:
	UnitedNations* m_mediator;
public:
	explicit Country(UnitedNations* mediator) :m_mediator(mediator) {}
	virtual ~Country() = default;
	virtual void Declare(string message) = 0;
	virtual void GetMessage(string message) = 0;
};

//Mediator
class UnitedNations
{
public:
	virtual ~UnitedNations() = default;
	virtual void setColleague1(Country* c) = 0;
	virtual void setColleague2(Country* c) = 0;
	virtual void Declare(string message, Country* colleague) = 0;
};

//ConcreteMediator
class UnitedNationsSecurityCouncil :public UnitedNations
{
private:
	Country* colleague1 = nullptr;
	Country* colleague2 = nullptr;

public:
	void setColleague1(Country* c)override;
	void setColleague2(Country* c)override;
	void Declare(string message, Country* colleague)override;
};

void UnitedNationsSecurityCouncil::setColleague1(Country* c)
{
	colleague1 = c;
}

void UnitedNationsSecurityCouncil::setColleague2(Country* c)
{
	colleague2 = c;
}

void UnitedNationsSecurityCouncil::Declare(string message, Country* colleague)
{
	if (colleague == colleague1)
		colleague2->GetMessage(message);
	else
		colleague1->GetMessage(message);
}


//ConcreteColleague
class USA :public Country
{
public:
	explicit USA(UnitedNations* mediator) :Country(mediator) {}
	void Declare(string message)override;
	void GetMessage(string message)override;
};

//ConcreteColleague
class Iraq :public Country
{
public:
	explicit Iraq(UnitedNations* mediator) :Country(mediator) {}
	void Declare(string message)override;
	void GetMessage(string message)override;
};


void USA::Declare(string message)
{
	m_mediator->Declare(message, this);
}

void USA::GetMessage(string message)
{
	cout << "美國獲得對方信息:" << message << endl;
}

void Iraq::Declare(string message)
{
	m_mediator->Declare(message, this);
}

void Iraq::GetMessage(string message)
{
	cout << "伊拉克獲得對方信息:" << message << endl;
}


int main()
{
	UnitedNationsSecurityCouncil UNSC;

	USA c1(&UNSC);
	Iraq c2(&UNSC);

	UNSC.setColleague1(&c1);
	UNSC.setColleague2(&c2);

	c1.Declare("不準研製核武器,否則要發動戰爭!");
	c1.Declare("我們沒有核武器,也不怕侵略。");
	system("pause");
	return 0;
}

 


優點


  • Mediator類 的出現減少了各個Colleague的耦合,使得可以獨立地改變和複用各個Colleague,這樣 Colleague之間可以相對獨立地使用。
  • 將對象間的一對多關聯 轉變 爲一對一的關聯,同事類只依賴中介者,減少了依賴,當然同時也降低了類間的耦合。這樣提高系統的靈活性,使得系統易於維護和擴展。
  • 使用中介者模式可以將對象的行爲和協作進行抽象,能夠比較靈活的處理對象間的相互作用。

缺點


  • 由於中介者對象封裝了系統中對象之間的交互,當同事類太多時,中介者的職責將很大,它會變得複雜而龐大,維護難度會逐漸增大

應用場景


  • 當對象之間的交互操作很多且每個對象的行爲操作都依賴彼此時,爲防止在修改一個對象的行爲時,同時涉及很多其他對象的行爲,可使用中介者模式

   在面向對象編程中,一個類必然會與其他的類發生依賴關係,完全獨立的類是沒有意義的。一個類同時依賴多個類的情況也相當普遍,既然存在這樣的情況,說明,一對多的依賴關係有它的合理性,適當的使用中介者模式可以使原本凌亂的對象關係清晰,但是如果濫用,則可能會帶來反的效果。一般來說,只有對於那種同事類之間是網狀結構的關係,纔會考慮使用中介者模式。可以將網狀結構變爲星狀結構,使同事類之間的關係變的清晰一些。

       中介者模式是一種比較常用的模式,也是一種比較容易被濫用的模式。對於大多數的情況,同事類之間的關係不會複雜到混亂不堪的網狀結構,因此,大多數情況下,將對象間的依賴關係封裝的同事類內部就可以的,沒有必要非引入中介者模式。濫用中介者模式,只會讓事情變的更復雜。


代理模式、外觀模式和中介者模式對比



當我們學完中介者模式是不是會覺得和此前講過的代理模式和外觀模式有些類似呢?現在我們一一來將它們進行對比。

代理模式和中介者模式

  • 代理模式是結構型設計模式,它有很多種類型,主要是在訪問對象時引入一定程度的間接性,由於有間接性,就可以附加多種的用途,比如進行權限控制。中介者模式則是爲了減少對象之間的相互耦合。雖然網上有很多代理模式和中介者模式的對比,但是在我看來這兩者實際上並沒有可比性,只是看起來有些類似罷了。

外觀模式和中介者模式

外觀模式主要是以封裝和隔離爲主要任務,中介者則是調停同事類之間的關係,因此,中介者具有部分業務的邏輯控制。主要區別爲: 

  • - 外觀模式的子系統如果脫離外觀模式還是可以運行的,而中介者模式增加了業務邏輯,同事類不能脫離中介者而獨自存在。 
  • - 外觀模式中,子系統是不知道外觀類的存在的,而中介者模式中,每個同事類都知道中介者。 
  • - 外觀模式將子系統的邏輯隱藏,用戶不知道子系統的存在,而中介者模式中,用戶知道同事類的存在。
     

 

發佈了209 篇原創文章 · 獲贊 73 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章