设计模式——中介者模式

中介者模式的定义为:Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly,and it lets you vary their interaction independently.(用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。)

中介者模式通用类图

从类图中看,中介者模式由以下几部分组成:

  • Mediator 抽象中介者角色 抽象中介者角色定义统一的接口,用于各同事角色之间的通信。

  • Concrete Mediator 具体中介者角色 具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。

  • Colleague 同事角色 每一个同事角色都知道中介者角色,而且与其他的同事角色通信的时候,一定要通过中 介者角色协作。每个同事类的行为分为两种:一种是同事本身的行为,比如改变对象本身的 状态,处理自己的行为等,这种行为叫做自发行为(Self-Method),与其他的同事类或中介 者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(DepMethod)。

这里用一个具体的例子来做说明,一群人参加一场赌博游戏:

  • 每个人初始都有100积分
  • 每局赌注都是一定数量的积分
  • 每局只会有一位赢家
  • 输家会从积分里扣除赌注相同的数值
  • 赢家则会赢得其他所有人输掉的积分之和

如果是我参加上面这个游戏,我肯定只会盯着自己的积分(钱包),不想别的玩家直接对我的钱包动手动脚,我也没权利去对别人的钱包动手动脚。而且我更不想在每局结算的时候,去算自己应该加多少分,谁谁谁应该扣多少分,我是来享受游戏的。

这时候就该荷官(中介者)出场了,这样每局关于其他玩家结算的事情都交给他全权处理,我只用管好我自己的积分就行。

以下是中介者的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class Mediator {
protected ConcreteColleague1 c1;
protected ConcreteColleague2 c2;
protected ConcreteColleague3 c3;

public void setC1(ConcreteColleague1 c1) {
this.c1 = c1;
}

public void setC2(ConcreteColleague2 c2) {
this.c2 = c2;
}

public void setC3(ConcreteColleague3 c3) {
this.c3 = c3;
}

public abstract int lostExceptC1(int num);
public abstract int lostExceptC2(int num);
public abstract int lostExceptC3(int num);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConcreteMediator extends Mediator {
@Override
public int lostExceptC1(int num) {
super.c2.decrease(num);
super.c3.decrease(num);
return num + num;
}

@Override
public int lostExceptC2(int num) {
super.c1.decrease(num);
super.c3.decrease(num);
return num + num;
}

@Override
public int lostExceptC3(int num) {
super.c1.decrease(num);
super.c2.decrease(num);
return num + num;
}
}

不难看出这位荷官,支持3个人进行游戏,每局都会从输家那里扣除积分,并计算出总分来。

下面是同事类及其具体实现类:

1
2
3
4
5
6
7
public abstract class Colleague {
protected Mediator mediator;

public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ConcreteColleague1 extends Colleague {
private int money = 100;

public ConcreteColleague1(Mediator mediator) {
super(mediator);
}

public void increase(int num) {
this.money += num;
System.out.println("colleague1's money is: " + money);
}

public void decrease(int num) {
this.money -= num;
System.out.println("colleague1's money is: " + money);
}

public void win(int num) {
int total = super.mediator.lostExceptC1(num);
this.increase(total);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ConcreteColleague2 extends Colleague {
private int money = 100;

public ConcreteColleague2(Mediator mediator) {
super(mediator);
}

public void increase(int num) {
this.money += num;
System.out.println("colleague2's money is: " + money);
}

public void decrease(int num) {
this.money -= num;
System.out.println("colleague2's money is: " + money);
}

public void win(int num) {
int total = super.mediator.lostExceptC2(num);
this.increase(total);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ConcreteColleague3 extends Colleague {
private int money = 100;

public ConcreteColleague3(Mediator mediator) {
super(mediator);
}

public void increase(int num) {
this.money += num;
System.out.println("colleague3's money is: " + money);
}

public void decrease(int num) {
this.money -= num;
System.out.println("colleague3's money is: " + money);
}

public void win(int num) {
int total = super.mediator.lostExceptC3(num);
this.increase(total);
}
}

以上3位玩家都能很好的对自己积分进行增减计算,但是涉及到多人同场竞技,就不得不依赖荷官(中介)来出手相助了。

最后看看整局游戏是如何进行的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Client {
public static void main(String[] args) {
// 荷官进场 (创建中介)
Mediator mediator = new ConcreteMediator();

// 玩家进场,上同一个桌(创造具体的同事类,以同一个中介)
ConcreteColleague1 c1 = new ConcreteColleague1(mediator);
ConcreteColleague2 c2 = new ConcreteColleague2(mediator);
ConcreteColleague3 c3 = new ConcreteColleague3(mediator);

// 荷官(中介)进行接管
mediator.setC1(c1);
mediator.setC2(c2);
mediator.setC3(c3);

// 游戏开始
System.out.println("---- round 1 ----");
c3.win(20);

System.out.println("---- round 2 ----");
c1.win(50);
// ...
}
}

结果:

1
2
3
4
5
6
7
8
9
---- round 1 ----
colleague1's money is: 80
colleague2's money is: 80
colleague3's money is: 140
---- round 2 ----
colleague2's money is: 30
colleague3's money is: 90
colleague1's money is: 180

优点

中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖, 同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合。

缺点

中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。

使用场景

中介者模式适用于多个对象之间紧密耦合的情况,紧密耦合的标准是:在类图中出现了蜘蛛网状结构。在这种情况下一定要考虑使用中介者模式,这有利于把蜘蛛网梳理为星型结构,使原本复杂混乱的关系变得清晰简单。

一些实际应用:

  • 机场调度中心
  • MVC框架
  • 媒体网关
  • 中介服务

设计模式——中介者模式
https://honosv.github.io/2023/09/23/设计模式——中介者模式/
作者
Nova
发布于
2023年9月23日
许可协议