Mediator
中介者模式:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,其可以改变他们之间的交互。
中介者模式又被称为 调停模式 ,它是 迪米特法则 的典型应用
在实现生活中也有很多的中介,比如房屋中介、婚姻介绍所等等。下面我们以婚姻中介为例来看下中介者模式。在没有婚姻中介之前,两个人从认识到恋爱完全看缘分,大千世界,相识相知很不容易,因为这就是一个多对多的选择过程,可以用图表示如下:
image.png
上图之间表示两个人之间的关系,可以看出来是十分混乱,而且随着节点增多,将会越来越复杂,一个节点和一个节点并不能保证直接认识,因为选老婆这个事中间还是不能通过太多的人。 当婚姻中介所出现后,上面的情况变成了如下:
image.png
人们全部通过中介来和对方认识,整个关系一下子就变得很清晰,不再那么杂乱无章,这就是解耦后的效果(每个人都能通过中介人事对方,岂不机会更大)。其实对应上图的形状,其实我个人很喜欢把它叫做中心开花模式

在程序中使用中介者模式也是为了达到解耦的效果,其对应的UML图如下:
3-1Q1161I532V0.gif

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  • 具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个集合来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

对于婚姻中介来说,也并不是每个人都能这样去相亲。因为至少你得在中介所登记下。这样人家才有你的联系方式,有结果了才能通知你。同样你药中介的联系方式,才能随时知道结果,以及通过中介去联系对方人员。这在中介者模式当中是一样的:中介者和同事都会互相持有对方引用。

1、场景描述

用程序实现上面例子中婚姻中介的逻辑。

2、实现

  1. /// <summary>
  2. /// 抽象中介者
  3. /// </summary>
  4. public abstract class AbstractMediator
  5. {
  6. /// <summary>
  7. /// 注册人员
  8. /// </summary>
  9. /// <param name="colleague"></param>
  10. public abstract void Register(AbstractColleague colleague);
  11. /// <summary>
  12. /// 介绍给对方认识,转发请求
  13. /// </summary>
  14. /// <param name="colleagueTo">对方人员编号</param>
  15. public abstract void Introduce(string code);
  16. }
  17. /// <summary>
  18. /// 具体中介角色-婚姻介绍所
  19. /// </summary>
  20. public class MarriageMediator : AbstractMediator
  21. {
  22. private List<AbstractColleague> colleagues = new();
  23. /// <summary>
  24. /// 婚介所介绍
  25. /// </summary>
  26. /// <param name="code">人员编号</param>
  27. public override void Introduce(string code)
  28. {
  29. Console.WriteLine("婚介所开始连线搭桥...");
  30. colleagues.FirstOrDefault(it => it.Code == code)?.Reveive();
  31. }
  32. /// <summary>
  33. /// 注册相亲人员
  34. /// </summary>
  35. /// <param name="colleague"></param>
  36. public override void Register(AbstractColleague colleague)
  37. {
  38. // 注册进婚介所
  39. colleagues.Add(colleague);
  40. // 将婚介所聚合赋值到具体人员(相当于现实中将婚介所的联系方式给到注册人)
  41. colleague.SetMediator(this);
  42. }
  43. }
  44. /// <summary>
  45. /// 抽象同事类
  46. /// </summary>
  47. public abstract class AbstractColleague
  48. {
  49. // 聚合中介者角色
  50. public AbstractMediator _mediator;
  51. // 人员编号,唯一
  52. public string Code { get; }
  53. public AbstractColleague(string code)
  54. {
  55. Code = code;
  56. }
  57. /// <summary>
  58. /// 设置中介者
  59. /// </summary>
  60. /// <param name="mediator"></param>
  61. public void SetMediator(AbstractMediator mediator)
  62. {
  63. _mediator = mediator;
  64. }
  65. /// <summary>
  66. /// 接收到认识邀请
  67. /// </summary>
  68. public abstract void Reveive();
  69. /// <summary>
  70. /// 发送认识邀请
  71. /// </summary>
  72. public abstract void Send();
  73. }
  74. /// <summary>
  75. /// 具体同事类角色 -- 张三
  76. /// </summary>
  77. public class User1Colleague : AbstractColleague
  78. {
  79. public User1Colleague(string code) : base(code)
  80. {
  81. }
  82. /// <summary>
  83. /// 收到消息
  84. /// </summary>
  85. public override void Reveive()
  86. {
  87. Console.WriteLine("张三收到认识邀请...");
  88. }
  89. public override void Send()
  90. {
  91. Console.WriteLine("张三看上了一个人,发出认识邀请...");
  92. _mediator.Introduce("200");
  93. }
  94. }
  95. /// <summary>
  96. /// 具体同事类角色 -- 张三
  97. /// </summary>
  98. public class User2Colleague : AbstractColleague
  99. {
  100. public User2Colleague(string code) : base(code)
  101. {
  102. }
  103. /// <summary>
  104. /// 收到消息
  105. /// </summary>
  106. public override void Reveive()
  107. {
  108. Console.WriteLine("李四收到认识邀请...");
  109. }
  110. public override void Send()
  111. {
  112. Console.WriteLine("李四看上了一个人,发出认识邀请...");
  113. _mediator.Introduce("100");
  114. }
  115. }
  116. // 客户端
  117. AbstractColleague colleague1 = new User1Colleague("100");
  118. AbstractColleague colleague2 = new User2Colleague("200");
  119. AbstractMediator mediator = new MarriageMediator();
  120. mediator.Register(colleague1);
  121. mediator.Register(colleague2);
  122. colleague1.Send();
  123. Console.WriteLine("***************************");
  124. colleague2.Send();

上面代码输出结果为:
image.png

3、优缺点

优点:

  • 解耦
  • 符合迪米特法则,对象之间保持最少的了解

缺点:

  • 由于对象之间交互全靠中介者协调,如果对象之间交互复杂,那么中介者也会随之复杂。

    4、应用场景

  • 系统中对象间存在较为复杂引用,导致依赖关系和结构混乱而无法复用的情况。

  • 想通过一个中间类来封装多个类的行为,但是又不想要太多的子类。