中介者模式(Mediator):
在現實生活中,有很多中介者模式的身影,例如QQ游戲平臺,聊天室、QQ群、短信平臺和房產中介,不論是QQ游戲還是QQ群,它們都是充當一個中間平臺,QQ用戶可以登錄這個中間平臺與其他QQ用戶進行交流,如果沒有這些中間平臺,我們如果想與朋友進行聊天的話,可能就需要當面才可以了,電話、短信也同樣是一個中間平臺,有了這個中間平臺,每個用戶都不要直接依賴與其他用戶,只需要依賴這個中間平臺就可以了,一切操作都由中間平臺去分發,中介者模式,定義了一個中介物件來封裝一系列物件之間的互動關系,中介者使各個物件之間不需要顯式地相互參考,從而使耦合性降低,而且可以獨立地改變它們之間的互動行為,

中介者模式的角色:

1)抽象中介者(Mediator):定義了同事物件到中介者物件的介面,
2)具體中介者(ConcreteMediator):實作抽象類的方法,它需要知道具體的同事類并從具體同事類接受訊息,向具體同事物件發出命令,
3)抽象同事類(Colleague):定義同事類的介面,保存中介者物件,提供同事物件互動的抽象方法,實作所有相互影響的同事類的公共功能,
4)具體同事類(ConcreteColleague):每個具體同事類只知道自己的行為,而不了解其他同事類的情況,但它們認識中介者物件,
示例:
以現實生活中打牌為例,若不使用中介者模式,
1 /// <summary> 2 /// 抽象牌友類 3 /// </summary> 4 public abstract class AbstractCardPartner 5 { 6 public int Money { get; set; } 7 8 public abstract void ChangeMoney(int money, AbstractCardPartner other); 9 }10 11 /// <summary>12 /// 牌友A13 /// </summary>14 public class PartnerA : AbstractCardPartner15 {16 public override void ChangeMoney(int money, AbstractCardPartner other)17 {18 Money += money;19 other.Money -= money;20 }21 }22 23 /// <summary>24 /// 牌友B25 /// </summary>26 public class PartnerB : AbstractCardPartner27 {28 public override void ChangeMoney(int money, AbstractCardPartner other)29 {30 Money += money;31 other.Money -= money;32 }33 }34 35 internal class Program36 {37 private static void Main(string[] args)38 {39 AbstractCardPartner A = new PartnerA();40 A.Money = 20;41 AbstractCardPartner B = new PartnerB();42 B.Money = 20;43 44 // A贏了B的錢減少45 A.ChangeMoney(5, B);46 Console.WriteLine("A 現在的錢是:{0}", A.Money); // 應該是2547 Console.WriteLine("B 現在的錢是:{0}", B.Money); // 應該是1548 49 // B贏了A的錢減少50 B.ChangeMoney(10, A);51 Console.WriteLine("A 現在的錢是:{0}", A.Money); // 應該是1552 Console.WriteLine("B 現在的錢是:{0}", B.Money); // 應該是2553 }54 }
這樣的實作確實解決了上面場景中的問題,并且使用了抽象類使具體牌友A和牌友B都依賴于抽象類,從而降低了同事類之間的耦合度,但是如果其中牌友A發生變化時,此時就會影響到牌友B的狀態,如果涉及的物件變多的話,這時候某一個牌友的變化將會影響到其他所有相關聯的牌友狀態,例如牌友A算錯了錢,這時候牌友A和牌友B的錢數都不正確了,如果是多個人打牌的話,影響的物件就會更多,這時候就會思考——能不能把算錢的任務交給程式或者算數好的人去計算呢,這時候就有了我們QQ游戲中的歡樂斗地主等牌類游戲了,
1 /// <summary> 2 /// 抽象牌友類 3 /// </summary> 4 public abstract class AbstractCardPartner 5 { 6 protected AbstractMediator mediator; 7 8 public int Money { get; set; } 9 10 public abstract void Change(int money, AbstractMediator mediator); 11 } 12 13 /// <summary> 14 /// 牌友A 15 /// </summary> 16 public class PartnerA : AbstractCardPartner 17 { 18 public PartnerA(int money) 19 { 20 Money = money; 21 } 22 23 public override void Change(int money, AbstractMediator mediator) 24 { 25 Console.WriteLine($"{nameof(PartnerA)}贏了"); 26 mediator.Change(money, this); 27 } 28 } 29 30 /// <summary> 31 /// 牌友B 32 /// </summary> 33 public class PartnerB : AbstractCardPartner 34 { 35 public PartnerB(int money) 36 { 37 Money = money; 38 } 39 40 public override void Change(int money, AbstractMediator mediator) 41 { 42 Console.WriteLine($"{nameof(PartnerB)}贏了"); 43 mediator.Change(money, this); 44 } 45 } 46 47 /// <summary> 48 /// 牌友B 49 /// </summary> 50 public class PartnerC : AbstractCardPartner 51 { 52 public PartnerC(int money) 53 { 54 Money = money; 55 } 56 57 public override void Change(int money, AbstractMediator mediator) 58 { 59 Console.WriteLine($"{nameof(PartnerC)}贏了"); 60 mediator.Change(money, this); 61 } 62 } 63 64 /// <summary> 65 /// 抽象中介者類 66 /// </summary> 67 public abstract class AbstractMediator 68 { 69 public abstract void Register(AbstractCardPartner cardPartner); 70 71 // cardPartner贏錢 72 public abstract void Change(int money, AbstractCardPartner cardPartner); 73 } 74 75 public class Mediator : AbstractMediator 76 { 77 private List<AbstractCardPartner> list = new List<AbstractCardPartner>(); 78 79 public override void Register(AbstractCardPartner cardPartner) 80 { 81 list.Add(cardPartner); 82 } 83 84 public override void Change(int money, AbstractCardPartner cardPartner) 85 { 86 foreach (var item in list) 87 { 88 if (item != cardPartner) 89 { 90 cardPartner.Money += money; 91 item.Money -= money; 92 } 93 } 94 } 95 } 96 97 internal class Program 98 { 99 private static void Main(string[] args)100 {101 AbstractMediator mediator = new Mediator();102 AbstractCardPartner A = new PartnerA(20);103 AbstractCardPartner B = new PartnerB(20);104 AbstractCardPartner C = new PartnerC(20);105 106 mediator.Register(A);107 mediator.Register(B);108 mediator.Register(C);109 110 // A贏了111 A.Change(5, mediator);112 Console.WriteLine("A 現在的錢是:{0}", A.Money); // 應該是30113 Console.WriteLine("B 現在的錢是:{0}", B.Money); // 應該是15114 Console.WriteLine("C 現在的錢是:{0}", C.Money); // 應該是15115 }116 }
在上面的實作代碼中,抽象中介者類保存了兩個抽象牌友類,如果新添加一個牌友類似時,此時就不得不去更改這個抽象中介者類,可以結合觀察者模式來解決這個問題,即抽象中介者物件保存抽象牌友的類別,然后添加Register和UnRegister方法來對該串列進行管理,然后在具體中介者類中修改AWin和BWin方法,遍歷串列,改變自己和其他牌友的錢數,這樣的設計還是存在一個問題——即增加一個新牌友時,此時雖然解決了抽象中介者類不需要修改的問題,但此時還是不得不去修改具體中介者類,即添加CWin方法,我們可以采用狀態模式來解決這個問題,
在寫中介者模式的時候,我發現我將其寫成了觀察者模式,后來仔細研究發現兩者還是有區別的:
中介者模式主要是起到一個協調的作用,它知道所有的同事類且同事類含有中介者物件,即我有事通知你,你幫我協調一下,
而觀察者模式側重在當一個物件的狀態發生變化時,能夠自動通知其他關聯物件,自動重繪物件狀態,
中介者模式的優缺點:
優點:
1)簡化了物件之間的關系,將系統的各個物件之間的相互關系進行封裝,將各個同事類解耦,使得系統變為松耦合,
2)提供系統的靈活性,使得各個同事物件獨立而易于復用,
缺點:
1)中介者模式中,中介者角色承擔了較多的責任,所以一旦這個中介者物件出現了問題,整個系統將會受到重大的影響,
2)新增加一個同事類時,不得不去修改抽象中介者類和具體中介者類,此時可以使用觀察者模式和狀態模式來解決這個問題,
中介者使用的場景:
1)一組定義良好的物件,現在要進行復雜的相互通信,
2)想通過一個中間類來封裝多個類中的行為,而又不想生成太多的子類,
參考:https://www.runoob.com/design-pattern/mediator-pattern.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/39927.html
標籤:設計模式
下一篇:部分設計模式對比分析
