中介者模式

# 分类

行为型模式

# 定义

中介者模式:(Mediator Pattern) 是用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。又叫调停者模式,是迪米特法则的典型应用。

# 意图

  • 中介者模式用来规范信息传递(类之间的交互行为)的方式。
  • 门面模式的初衷很相似。

# 应用场景

  • 主要解决?对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂。同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
  • 何时使用?中介者模式一般应用于一组对象定义良好,但是以复杂的方式进行通信的场合。多个对象相互耦合,产生了混乱的相互依赖关系,形成网状结构
  • 如何解决?中介者模式将多个对象之间的网状结构分离成为星型结构

应用实例

  • 类似于联合国组织这样的机构就是一个中介者。
  • 公司各部门的主管
  • 中国加入WTO之前是各个国家相互贸易,结构复杂,现在是各个国家通过WTO来互相贸易。
  • 机场调度指挥中心系统。
  • 地铁NCC线网指挥中心。
  • 煤矿调度指挥中心。
  • 中介服务。
  • MVC框架,其中C(控制器)就是M(模型)和V(视图)的中介者。
  • WinForm窗体程序控件的交互是典型的中介者模式。(每个控件都封装完好,不可能引入其他控件对象,通信时集中通过Form来完成)。

# 角色与结构图

  • Mediator:抽象中介者角色 抽象中介者角色定义统一的接口用于各同事角色之间的通信。
  • ConcreteMediator 具体中介者角色 具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。
  • Colleague 同事角色
    • 每个同事角色都知道中介者角色,而且与其它同事角色通信的时候,一定要通过中介者角色协作。
    • 每个同事类的行为分为两种:
      • 第一种是同事本身的行为,比如改变对象本身的状态,处理自己的行为等等,这种方法叫做自发行为,与其它同事或中介者没有任何的依赖;
      • 第二种是必须依赖中介者才能完成的行为,叫做依赖方法。

下图解释了中介者模式中各角色的作用

<<------------------------中介者模式结构图--------------------------->>

# 示例代码

// 抽象中介者类
abstract class Mediator{
  public abstract void Send(string message, Colleague colleague);
 
  //其他业务逻辑
  //public abstract void DoSomething();
}
// 抽象同事类
abstract class Colleague{
  protected Mediator mediator;
  
  //这样写是为了保证同事类中必须有中介者
  public Colleague(Mediator mediator){
    this.mediator = mediator;
  }
}
// 具体同事类1
class ConcreateColleague1 : Colleague{
  public ConcreateColleague(Mediator mediator):base(mediator){

  }

  public void Send(string message){
    mediator.Send(message, this);
  }

  public void Notify(string message){
    Console.WriteLine("同事1得到信息:" + message);
  }
}
// 具体同事类2
class ConcreateColleague2 : Colleague{
  public ConcreateColleague(Mediator mediator):base(mediator){

  }

  public void Send(string message){
    mediator.Send(message, this);
  }

  public void Notify(string message){
    Console.WriteLine("同事2得到信息:" + message);
  }
}
// 具体中介者类
class ConcreteMediator : Mediator{
  private ConcreteColleague1 colleague1;
  private ConcreteColleague2 colleague2;

  //这样写说明中介者中可以只拥有部分同事对象,注意区分同事类构造函数中的中介者参数
  public ConcreteColleague1 Colleague1{
    set {colleague1 = value;}
  }

   public ConcreteColleague2 Colleague2{
    set {colleague2 = value;}
  }

  public override void Send(string message, Colleague colleague){
    if(colleague == colleague1){
      colleague2.Notify(message);
    }else{
      colleague1.Notify(message);
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 客户端
class Client{
    static void main(string[] args){
      ConcreateMediator m = new ConcreateMediator();

      ConcreteColleague1 c1 = new ConcreteColleague1(m);
      ConcreteColleague1 c2 = new ConcreteColleague2(m);

      m.Colleague1 = c1;
      m.Colleague2 = c2;

      c1.Send("吃过饭了吗?");
      c2.send("没有呢,你打算请客?");

      Console.Read();
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 优点

  • 符合迪米特法则
  • 体现分层设计思想,分层是开发人员分离复杂系统时最常用、最普通的技术。
  • 降低了复杂度,将对象间的一对多(Colleague vs Colleagues)的通信协议转变成为一对一(Mediator vs Colleague)
  • 中介者模式中Mediator的出现实现了Colleague之间交互行为的集中控制,减少了各个Colleague的耦合,使得可以独立地改变和复用各个Colleague类和Mediator类。
  • 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统,从而能从整体上审视对象间的交互关系。

# 缺点

  • 由于ConcreteMediator控制的集中化,随着具体的Colleague类的增多,这样就把Colleague之间交互复杂性变为了中介者的复杂性,这就使得中介者会变得比任何一个ConcreteColleague都复杂。(这种复杂性类似简单工厂那样的条件耦合)

# 小结

  • 如果对象之间的关系原本一目了然,中介者对象的加入便是画蛇添足。
  • 中介者模式在定义上比较松散,在结构上和观察者模式命令模式十分相似,而应用的目的又与结构模式中的门面模式有些相似。

与门面模式不同之处

  • 门面模式是介于客户程序与子系统之间的,中介者模式是介于子系统与子系统之间的。
  • 门面模式是将原有的复杂逻辑提取到一个统一的接口,简化客户对逻辑的使用。它是被客户所感知的,而原有的复杂逻辑则被隐藏了起来。
  • 中介者模式并没有改变客户原有的使用习惯,它是隐藏在原有逻辑后面的,使得代码逻辑更加清晰可用。
  • 中介者模式很容易在系统中应用,也很容易在系统中误用,当系统出现了“多对多”交互复杂的对象群时,不要急于使用中介者模式,而要先反思你的系统设计在设计上是不是合理。
  • 将一个系统分割成许多对象通常可以增加其复用性,但是对象间相互连接的激增又会降低其可复用性。
  • 场景中增加一个中介者,然后分别传递给同事类中,这些同事类都具有相同的特性:只负责处理自己的活动(行为),与自己无关的活动(有相互依赖关系的)就丢给中介者处理。这样结构会变得更加清晰,类间的耦合度减少,代码质量也有了提升。
  • 关键代码?中介者模式的关键之处在于将多个Colleague对象之间的通信封装到一个类中单独处理。
  • 注意不要在职责混乱时使用该模式。
  • 并不是存在依赖关系就的使用中介者模式,使用这个模式要量力而行。衡量类之间关系的耦合程度就看UML类图中是否出现了蜘蛛网结构

# 一句话概括

  • 中介者集中控制对象间的消息传递行为Mediator Send Message Between ConcreteColleague
上次更新: 2025/03/22, 13:47:44
最近更新
01
Git问题集合
01-29
02
安装 Nginx 服务器
01-25
03
安装 Docker 容器
01-25
更多文章>
×
×