中介模式

參考
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游戲中計算歡樂豆的程序出錯了,這樣會造成重大的影響。
  • 新增加一個同事類時,不得不去修改抽象中介者類和具體中介者類,此時可以使用觀察者模式和狀態模式來解決這個問題。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容