.Net行為型設(shè)計(jì)模式之中介者模式(Mediator)
一、動(dòng)機(jī)(Motivate)
為什么要使用中介者模式呢?如果不使用中介者模式的話(huà),各個(gè)同事對(duì)象將會(huì)相互進(jìn)行引用,如果每個(gè)對(duì)象都與多個(gè)對(duì)象進(jìn)行交互時(shí),將會(huì)形成如下圖所示的網(wǎng)狀結(jié)構(gòu)。

從上圖可以發(fā)現(xiàn),如果不使用中介者模式的話(huà),每個(gè)對(duì)象之間過(guò)度耦合,這樣的既不利于類(lèi)的復(fù)用也不利于擴(kuò)展。如果引入了中介者模式,那么對(duì)象之間的關(guān)系將變成星型結(jié)構(gòu),采用中介者模式之后會(huì)形成如下圖所示的結(jié)構(gòu):

從上圖可以發(fā)現(xiàn),使用中介者模式之后,任何一個(gè)類(lèi)的變化,只會(huì)影響中介者和類(lèi)本身,不像之前的設(shè)計(jì),任何一個(gè)類(lèi)的變化都會(huì)引起其關(guān)聯(lián)所有類(lèi)的變化。這樣的設(shè)計(jì)大大減少了系統(tǒng)的耦合度。
在軟件構(gòu)建過(guò)程中,經(jīng)常會(huì)出現(xiàn)多個(gè)對(duì)象互相關(guān)聯(lián)交互的情況,對(duì)象之間常常會(huì)維持一種復(fù)雜的引用關(guān)系,如果遇到一些需求的更改,這種直接的引用關(guān)系將面臨不斷地變化。
在這種情況下,我們可使用一個(gè)“中介對(duì)象”來(lái)管理對(duì)象間的關(guān)聯(lián)關(guān)系,避免相互交互的對(duì)象之間的緊耦合引用關(guān)系,從而更好地抵御變化。
二、意圖(Intent)
定義了一個(gè)中介對(duì)象來(lái)封裝一系列對(duì)象之間的交互關(guān)系。中介者使各個(gè)對(duì)象之間不需要顯式地相互引用,從而使耦合性降低,而且可以獨(dú)立地改變它們之間的交互行為。 ——《設(shè)計(jì)模式》GoF
三、結(jié)構(gòu)圖(Structure)

四、模式的組成
可以看出,在中介者模式的結(jié)構(gòu)圖有以下角色:
(1)、抽象中介者角色(Mediator):在里面定義各個(gè)同事之間交互需要的方法,可以是公共的通信方法,也可以是小范圍的交互方法。
(2)、具體中介者角色(ConcreteMediator):它需要了解并維護(hù)各個(gè)同事對(duì)象,并負(fù)責(zé)具體的協(xié)調(diào)各同事對(duì)象的交互關(guān)系。
(3)、抽象同事類(lèi)(Colleague):通常為抽象類(lèi),主要約束同事對(duì)象的類(lèi)型,并實(shí)現(xiàn)一些具體同事類(lèi)之間的公共功能,比如,每個(gè)具體同事類(lèi)都應(yīng)該知道中介者對(duì)象,也就是具體同事類(lèi)都會(huì)持有中介者對(duì)象,都可以到這個(gè)類(lèi)里面。
(4)、具體同事類(lèi)(ConcreteColleague):實(shí)現(xiàn)自己的業(yè)務(wù),需要與其他同事通信時(shí)候,就與持有的中介者通信,中介者會(huì)負(fù)責(zé)與其他同事類(lèi)交互。
五、中介者模式的代碼實(shí)現(xiàn)
中介者模式在現(xiàn)實(shí)生活中也有類(lèi)似的例子,不論是QQ群或者是微信群,或者手提電話(huà),它們都是充當(dāng)一個(gè)中間平臺(tái),QQ用戶(hù)可以登錄這個(gè)中間平臺(tái)與其他QQ用戶(hù)進(jìn)行交流,如果沒(méi)有這些中間平臺(tái),我們?nèi)绻肱c朋友進(jìn)行聊天的話(huà),可能就需要當(dāng)面才可以了。比如:在公司管理過(guò)程中,就會(huì)涉及到各個(gè)部門(mén)之間的協(xié)調(diào)和合作,如何各個(gè)部門(mén)直接來(lái)溝通,看著好像直接高效,其實(shí)不然。各個(gè)部門(mén)之間為了完成一個(gè)工作,溝通協(xié)調(diào)就需要一個(gè)人來(lái)做這個(gè)工作,誰(shuí)呢?總經(jīng)理,我們這里就把總經(jīng)理定義為成總的管理者,各個(gè)部門(mén)需要向他匯報(bào)和發(fā)起工作請(qǐng)求。
static void Main(String[] args)
{
President mediator = new President();
Market market = new Market(mediator);
Development development = new Development(mediator);
Financial financial = new Financial(mediator);
mediator.SetFinancial(financial);
mediator.SetDevelopment(development);
mediator.SetMarket(market);
market.Process();
market.Apply();
}
//抽象中介者角色
public interface Mediator
{
void Command(Department department);
}
//總經(jīng)理--相當(dāng)于具體中介者角色
public sealed class President : Mediator
{
//總經(jīng)理有各個(gè)部門(mén)的管理權(quán)限
private Financial _financial;
private Market _market;
private Development _development;
public void SetFinancial(Financial financial)
{
this._financial = financial;
}
public void SetDevelopment(Development development)
{
this._development = development;
}
public void SetMarket(Market market)
{
this._market = market;
}
public void Command(Department department)
{
if (department.GetType() == typeof(Market))
{
_financial.Process();
}
}
}
//同事類(lèi)的接口
public abstract class Department
{
//持有中介者(總經(jīng)理)的引用
private Mediator mediator;
protected Department(Mediator mediator)
{
this.mediator = mediator;
}
public Mediator GetMediator
{
get { return mediator; }
private set { this.mediator = value; }
}
//做本部門(mén)的事情
public abstract void Process();
//向總經(jīng)理發(fā)出申請(qǐng)
public abstract void Apply();
}
//開(kāi)發(fā)部門(mén)
public sealed class Development : Department
{
public Development(Mediator m) : base(m) { }
public override void Process()
{
Console.WriteLine("我們是開(kāi)發(fā)部門(mén),要進(jìn)行項(xiàng)目開(kāi)發(fā),沒(méi)錢(qián)了,需要資金支持!");
}
public override void Apply()
{
Console.WriteLine("專(zhuān)心科研,開(kāi)發(fā)項(xiàng)目!");
}
}
//財(cái)務(wù)部門(mén)
public sealed class Financial : Department
{
public Financial(Mediator m) : base(m) { }
public override void Process()
{
Console.WriteLine("匯報(bào)工作!沒(méi)錢(qián)了,錢(qián)太多了!怎么花?");
}
public override void Apply()
{
Console.WriteLine("數(shù)錢(qián)!");
}
}
//市場(chǎng)部門(mén)
public sealed class Market : Department
{
public Market(Mediator mediator) : base(mediator) { }
public override void Process()
{
Console.WriteLine("匯報(bào)工作!項(xiàng)目承接的進(jìn)度,需要資金支持!");
GetMediator.Command(this);
}
public override void Apply()
{
Console.WriteLine("跑去接項(xiàng)目!");
}
}六、中介者模式的實(shí)現(xiàn)要點(diǎn):
將多個(gè)對(duì)象間復(fù)雜的關(guān)聯(lián)關(guān)系解耦,Mediator模式將多個(gè)對(duì)象間的控制邏輯進(jìn)行集中管理,變“多個(gè)對(duì)象互相關(guān)聯(lián)”為“多個(gè)對(duì)象和一個(gè)中介者關(guān)聯(lián)”,簡(jiǎn)化了系統(tǒng)的維護(hù),抵御了可能的變化。隨著控制邏輯的復(fù)雜化,Mediator具體對(duì)象的實(shí)現(xiàn)可能相當(dāng)復(fù)雜。這時(shí)候可以對(duì)Mediator對(duì)象進(jìn)行分解處理。
- Facade模式是解耦系統(tǒng)外到系統(tǒng)內(nèi)(單向)的對(duì)相關(guān)聯(lián)關(guān)系
- Mediator模式是解耦系統(tǒng)內(nèi)各個(gè)對(duì)象之間(雙向)的關(guān)聯(lián)關(guān)系
1、中介者模式的優(yōu)點(diǎn)
(1)、松散耦合:中介者模式通過(guò)把多個(gè)同事對(duì)象之間的交互封裝到中介對(duì)象里面,從而使得對(duì)象之間松散耦合,基本上可以做到互不依賴(lài)。這樣一來(lái),同時(shí)對(duì)象就可以獨(dú)立的變化和復(fù)用,不再“牽一發(fā)動(dòng)全身”
(2)、集中控制交互:多個(gè)同事對(duì)象的交互,被封裝在中介者對(duì)象里面集中管理,使得這些交互行為發(fā)生變化的時(shí)候,只需要修改中介者就可以了。
(3)、多對(duì)多變?yōu)橐粚?duì)多:沒(méi)有中介者模式的時(shí)候,同事對(duì)象之間的關(guān)系通常是多對(duì)多,引入中介者對(duì)象后,中介者和同事對(duì)象的關(guān)系通常變?yōu)殡p向的一對(duì)多,這會(huì)讓對(duì)象的關(guān)系更容易理解和實(shí)現(xiàn)。
2、中介者模式的缺點(diǎn)
過(guò)多集中化:如果同事對(duì)象之間的交互非常多,而且比較復(fù)雜,當(dāng)這些復(fù)雜性全都集中到中介者的時(shí)候,會(huì)導(dǎo)致中介者對(duì)象變的十分復(fù)雜,而且難于維護(hù)和管理。
七、.NET 中介者模式的實(shí)現(xiàn)
根據(jù)我個(gè)人的理解,微軟的ASP.NET MVC開(kāi)發(fā)模式就是一個(gè)中介者模式的很好的實(shí)現(xiàn),其中C就是Controller,也就是中文所說(shuō)的控制器,控制器就是一個(gè)中介者,M和V和它打交道,具體的情況大家可以去查看相關(guān)資料,這方面的資料還是很多的。
到此這篇關(guān)于.Net行為型設(shè)計(jì)模式之中介者模式(Mediator)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- .Net行為型設(shè)計(jì)模式之備忘錄模式(Memento)
- .Net行為型設(shè)計(jì)模式之訪問(wèn)者模式(Visitor)
- .Net行為型設(shè)計(jì)模式之職責(zé)鏈模式(Chain of Responsibility)
- .Net行為型設(shè)計(jì)模式之策略模式(Stragety)
- .Net行為型設(shè)計(jì)模式之狀態(tài)模式(State)
- .Net行為型設(shè)計(jì)模式之觀察者模式(Observer)
- .Net行為型設(shè)計(jì)模式之迭代器模式(Iterator)
- .Net行為型設(shè)計(jì)模式之命令模式(Command)
- .Net行為型設(shè)計(jì)模式之模板方法模式(Template?Method)
- .Net行為型設(shè)計(jì)模式之解釋器模式(Interpreter)
相關(guān)文章
ASP.NET Core應(yīng)用程序配置文件AppSetting.json
這篇文章介紹了ASP.NET Core應(yīng)用程序配置文件AppSetting.json,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02
初識(shí) ASP.NET Membership 用戶(hù)管理
Membership 是用做用戶(hù)管理,進(jìn)行身份認(rèn)證使用的。通過(guò)ASP.NET Membership,我們可以創(chuàng)建用戶(hù)、刪除用戶(hù)和編輯用戶(hù)屬性。所以這是一個(gè)實(shí)現(xiàn)登錄相關(guān)控件的底層框架。2016-04-04
學(xué)會(huì)區(qū)分Visual Studio 2005,Visual Studio 2005 Team System和MSDN P
學(xué)會(huì)區(qū)分Visual Studio 2005,Visual Studio 2005 Team System和MSDN Premium 訂閱的各個(gè)版本...2007-01-01
ASP.NET中 ObjectDataSource控件的DataObjectTypeName屬性
本文主要介紹ObjectDataSource控件和DataObjectTypeName屬性的用法,希望能給小伙伴們一些幫助。2016-04-04
.Net Core使用SignalR實(shí)現(xiàn)斗地主游戲
本文詳細(xì)講解了.Net Core使用SignalR實(shí)現(xiàn)斗地主游戲的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01

