參考
C#設計模式(18)——中介者模式(Mediator Pattern)
設計模式讀書筆記-----中介者模式
實用模式之中介者模式
在面向對象編程中,一個類必然會與其他的類發生依賴關系,完全獨立的類是沒有意義的。一個類同時依賴多個類的情況也相當普遍,既然存在這樣的情況,說明,一對多的依賴關系有它的合理性,適當的使用中介者模式可以使原本凌亂的對象關系清晰,但是如果濫用,則可能會帶來反的效果。一般來說,只有對于那種同事類之間是網狀結構的關系,才會考慮使用中介者模式。可以將網狀結構變為星狀結構,使同事類之間的關系變的清晰一些。
中介者模式是一種比較常用的模式,也是一種比較容易被濫用的模式。對于大多數的情況,同事類之間的關系不會復雜到混亂不堪的網狀結構,因此,大多數情況下,將對象間的依賴關系封裝的同事類內部就可以的,沒有必要非引入中介者模式。濫用中介者模式,只會讓事情變的更復雜。
以打牌為例,某一個牌友的變化將會影響到其他所有相關聯的牌友狀態。例如牌友A算錯了錢,這時候牌友A和牌友B的錢數都不正確了,如果是多個人打牌的話,影響的對象就會更多。這時候就會思考——能不能把算錢的任務交給程序或者算數好的人去計算呢,這時候就有了我們QQ游戲中的歡樂斗地主等牌類游戲了。所以上面的設計,我們還是有進一步完善的方案的,即加入一個中介者對象來協調各個對象之間的關聯,這也就是中介者模式的應用了。
** 未使用中介者:**
// 抽象牌友類
public abstract class AbstractCardPartner
{
public int MoneyCount { get; set; }
public AbstractCardPartner()
{
MoneyCount = 0;
}
public abstract void ChangeCount(int Count, AbstractCardPartner other);
}
// 牌友A類
public class ParterA : AbstractCardPartner
{
public override void ChangeCount(int Count, AbstractCardPartner other)
{
this.MoneyCount += Count;
other.MoneyCount -= Count;
}
}
// 牌友B類
public class ParterB : AbstractCardPartner
{
public override void ChangeCount(int Count, AbstractCardPartner other)
{
this.MoneyCount += Count;
other.MoneyCount -= Count;
}
}
class Program
{
// A,B兩個人打牌
static void Main(string[] args)
{
AbstractCardPartner A = new ParterA();
A.MoneyCount = 20;
AbstractCardPartner B = new ParterB();
B.MoneyCount = 20;
// A 贏了則B的錢就減少
A.ChangeCount(5, B);
Console.WriteLine("A 現在的錢是:{0}", A.MoneyCount);// 應該是25
Console.WriteLine("B 現在的錢是:{0}", B.MoneyCount); // 應該是15
// B贏了A的錢也減少
B.ChangeCount(10, A);
Console.WriteLine("A 現在的錢是:{0}", A.MoneyCount); // 應該是15
Console.WriteLine("B 現在的錢是:{0}", B.MoneyCount); // 應該是25
Console.Read();
}
}
使用中介者:
namespace MediatorPattern
{
// 抽象牌友類
public abstract class AbstractCardPartner
{
public int MoneyCount { get; set; }
public AbstractCardPartner()
{
MoneyCount = 0;
}
public abstract void ChangeCount(int Count, AbstractMediator mediator);
}
// 牌友A類
public class ParterA : AbstractCardPartner
{
// 依賴與抽象中介者對象
public override void ChangeCount(int Count, AbstractMediator mediator)
{
mediator.AWin(Count);
}
}
// 牌友B類
public class ParterB : AbstractCardPartner
{
// 依賴與抽象中介者對象
public override void ChangeCount(int Count, AbstractMediator mediator)
{
mediator.BWin(Count);
}
}
// 抽象中介者類
public abstract class AbstractMediator
{
protected AbstractCardPartner A;
protected AbstractCardPartner B;
public AbstractMediator(AbstractCardPartner a, AbstractCardPartner b)
{
A = a;
B = b;
}
public abstract void AWin(int count);
public abstract void BWin(int count);
}
// 具體中介者類
public class MediatorPater : AbstractMediator
{
public MediatorPater(AbstractCardPartner a, AbstractCardPartner b)
: base(a, b)
{
}
public override void AWin(int count)
{
A.MoneyCount += count;
B.MoneyCount -= count;
}
public override void BWin(int count)
{
B.MoneyCount += count;
A.MoneyCount -= count;
}
}
class Program
{
static void Main(string[] args)
{
AbstractCardPartner A = new ParterA();
AbstractCardPartner B = new ParterB();
// 初始錢
A.MoneyCount = 20;
B.MoneyCount = 20;
AbstractMediator mediator = new MediatorPater(A, B);
// A贏了
A.ChangeCount(5, mediator);
Console.WriteLine("A 現在的錢是:{0}", A.MoneyCount);// 應該是25
Console.WriteLine("B 現在的錢是:{0}", B.MoneyCount); // 應該是15
// B 贏了
B.ChangeCount(10, mediator);
Console.WriteLine("A 現在的錢是:{0}", A.MoneyCount);// 應該是15
Console.WriteLine("B 現在的錢是:{0}", B.MoneyCount); // 應該是25
Console.Read();
}
}
}
從上面實現代碼可以看出,此時牌友A和牌友B都依賴于抽象的中介者類,這樣如果其中某個牌友類變化只會影響到,只會影響到該變化牌友類本身和中介者類,從而解決前面實現代碼出現的問題,具體的運行結果和前面實現結果一樣.
在上面的實現代碼中,抽象中介者類保存了兩個抽象牌友類,如果新添加一個牌友類時,此時就不得不去更改這個抽象中介者類。可以結合觀察者模式來解決這個問題,即抽象中介者對象保存抽象牌友的類別,然后添加Register和UnRegister方法來對該列表進行管理,然后在具體中介者類中修改AWin和BWin方法,遍歷列表,改變自己和其他牌友的錢數。這樣的設計還是存在一個問題——即增加一個新牌友時,此時雖然解決了抽象中介者類不需要修改的問題,但此時還是不得不去修改具體中介者類,即添加CWin方法,我們可以采用狀態模式來解決這個問題,關于狀態模式的介紹將會在下一專題進行分享。
中介者模式具有以下幾點優點:
- 簡化了對象之間的關系,將系統的各個對象之間的相互關系進行封裝,將各個同事類解耦,使得系統變為松耦合。
- 提供系統的靈活性,使得各個同事對象獨立而易于復用。
然而,中介者模式也存在對應的缺點:
- 中介者模式中,中介者角色承擔了較多的責任,所以一旦這個中介者對象出現了問題,整個系統將會受到重大的影響。例如,QQ游戲中計算歡樂豆的程序出錯了,這樣會造成重大的影響。
- 新增加一個同事類時,不得不去修改抽象中介者類和具體中介者類,此時可以使用觀察者模式和狀態模式來解決這個問題。