设计模式-行为型-中介者模式
中介者模式(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 /// 牌友a 13 /// </summary> 14 public class partnera : abstractcardpartner 15 { 16 public override void changemoney(int money, abstractcardpartner other) 17 { 18 money += money; 19 other.money -= money; 20 } 21 } 22 23 /// <summary> 24 /// 牌友b 25 /// </summary> 26 public class partnerb : abstractcardpartner 27 { 28 public override void changemoney(int money, abstractcardpartner other) 29 { 30 money += money; 31 other.money -= money; 32 } 33 } 34 35 internal class program 36 { 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); // 应该是25 47 console.writeline("b 现在的钱是:{0}", b.money); // 应该是15 48 49 // b赢了a的钱减少 50 b.changemoney(10, a); 51 console.writeline("a 现在的钱是:{0}", a.money); // 应该是15 52 console.writeline("b 现在的钱是:{0}", b.money); // 应该是25 53 } 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); // 应该是30 113 console.writeline("b 现在的钱是:{0}", b.money); // 应该是15 114 console.writeline("c 现在的钱是:{0}", c.money); // 应该是15 115 } 116 }
在上面的实现代码中,抽象中介者类保存了两个抽象牌友类,如果新添加一个牌友类似时,此时就不得不去更改这个抽象中介者类。可以结合观察者模式来解决这个问题,即抽象中介者对象保存抽象牌友的类别,然后添加register和unregister方法来对该列表进行管理,然后在具体中介者类中修改awin和bwin方法,遍历列表,改变自己和其他牌友的钱数。这样的设计还是存在一个问题——即增加一个新牌友时,此时虽然解决了抽象中介者类不需要修改的问题,但此时还是不得不去修改具体中介者类,即添加cwin方法,我们可以采用状态模式来解决这个问题。
在写中介者模式的时候,我发现我将其写成了,后来仔细研究发现两者还是有区别的:
中介者模式主要是起到一个协调的作用,它知道所有的同事类且同事类含有中介者对象,即我有事通知你,你帮我协调一下。
而观察者模式侧重在当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
中介者模式的优缺点:
优点:
1)简化了对象之间的关系,将系统的各个对象之间的相互关系进行封装,将各个同事类解耦,使得系统变为松耦合。
2)提供系统的灵活性,使得各个同事对象独立而易于复用。
缺点:
1)中介者模式中,中介者角色承担了较多的责任,所以一旦这个中介者对象出现了问题,整个系统将会受到重大的影响。
2)新增加一个同事类时,不得不去修改抽象中介者类和具体中介者类,此时可以使用观察者模式和状态模式来解决这个问题。
中介者使用的场景:
1)一组定义良好的对象,现在要进行复杂的相互通信。
2)想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
参考:
上一篇: 吃什么东西补肾?想要肾气足吃它就对了!