设计模式-行为型-中介者模式

中介者模式(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)想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

参考:https://www.runoob.com/design-pattern/mediator-pattern.html

(0)

相关推荐

  • 设计模式------中介者模式

    中介者模式: 定义一个对象来封装一系列对象的交互. 中介者的四个角色: 1.Mediator(抽象中介者) 2.ConcreteMediator(具体中介者) 3.Colleague(抽象同事类) 4 ...

  • Java设计模式-中介者模式

    https://www.shengchulai.com/blog-CiTs5E8tUf.htm 前言 小时候钟爱战争片,<地道战>.<鸡毛信>.<铁道游击队>一系列 ...

  • 图解Java设计模式之中介者模式

    智能家庭项目 传统方案解决智能家庭管理问题 中介者模式基本介绍 中介者模式的原理类图 中介者模式 - 智能家庭的操作流程 中介者模式的注意事项和细节 智能家庭项目 1)智能家庭包括各种设备,闹钟.咖啡 ...

  • MediatorPattern中介者模式

    中介者模式 1.定义 使用一个中介对象封装一系列的对象交互,中介者使用对象不需要显式的相互作用,从而实降现低耦合度,且可以独立改变被封装的一些列对象之间的交互. 中介者模式也叫做调停者模式:对象之间的 ...

  • PHP设计模式之中介者模式

    PHP设计模式之中介者模式 上回说道,我们在外打工的经常会和一类人有很深的接触,那就是房产中介.大学毕业后马上就能在喜欢的城市买到房子的X二代不在我们的考虑范围内哈.既然需要长期的租房,那么因为工作或 ...

  • 通俗易懂设计模式解析——中介者模式

    前言 今天我们一起看看中介者模式,怎么去理解这个模式呢?说起来也简单.好理解.生活中我们租房经常都是通过中介来实现的.一般租房要么是房东直租要么是中介.那么今天要讲的中介者模式和租房的这个中介是否有关 ...

  • 行为型模式之中介者模式

    在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是"网状结构",它要求每个对象都必须知道它需要交互的对象. 如果把这种"网状结构"改为& ...

  • 设计模式-创建型-抽象工厂模式

    前一章节,我们介绍了简单工厂模式以及工厂方法模式,但是这两种模式都存在一定的局限性,只能生产某一类型下的某一种产品,如果需求变更,同类型下出现了不同的产品,比如芝士披萨不仅有口味上的不同,同时存在外观 ...

  • 无废话设计模式(17)行为型模式--中介者模式

    0-前言 中介者模式定义(Mediator): 用一个中介对象来封装一系列的对象交互. 中介者对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互. 1-实现 1-1.简单UM ...

  • [PHP小课堂]PHP设计模式之中介者模式

    [PHP小课堂]PHP设计模式之中介者模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料