设计模式18-Mediator

本文最后更新于:3 years ago

调停者模式

  调停者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个调停类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。调停者模式属于 行为型模式

如果想了解调停者模式的具体的介绍,菜鸟教程介绍得比较详细↓
菜鸟教程-调停者模式

结构图


优缺点

优点:

1、降低了类的复杂度,将一对多转化成了一对一。
2、各个类之间的解耦。
3、符合迪米特原则

缺点:

调停者会庞大,变得复杂难以维护。

使用场景

1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。
2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

实现代码

调停者模式和上一章说的外观模式是思想上是很相似的,但是调停者是解决系统内部中的多个对象之间复杂的关系的,所以二者面对的对象是不一样的。
如下图所示:


本来准备介绍的栗子比较简单,然后想想还是仔细介绍一下吧

Mediator模式中Mediator是抽象中介者,提供了同事对象注册与转发同事对象信息的抽象方法;
Colleague是抽象同事类,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能;
ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接收消息,向具体同事对象发出命令,协调各个同事角色之间的交互关系;
ConcreteColleague是具体同事类,每个具体同事只知道自己的行为,而不了解其它同事类的情况,但它们却都认识中介者对象。

这里我们模拟的是,聊天室中当A发送消息时,B、C都能接收到,并且当接收到时,返回收到的信息。B、C同理

代码如下:

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
public class Main {
public static void main(String[] args) {
//构建中介者
Mediator mediator = new ConcreteMediator();

//构建具体同事类
Colleague colleagueA = new ConcreteColleagueA();
Colleague colleagueB = new ConcreteColleagueB();
Colleague colleagueC = new ConcreteColleagueC();

//注册同事
mediator.register(colleagueA);
mediator.register(colleagueB);
mediator.register(colleagueC);

//发送消息
colleagueA.send();
colleagueB.send();
colleagueC.send();
}
}

//抽象中介者
public abstract class Mediator {
abstract void register(Colleague colleague);

abstract void relay(Colleague colleague);
}

//抽象同事类
public abstract class Colleague {
protected Mediator mediator;

public void setMedium(Mediator mediator) {
this.mediator = mediator;
}

abstract void receive();

abstract void send();
}

//中介者对象
public class ConcreteMediator extends Mediator {
List<Colleague> colleagues;

public ConcreteMediator() {
colleagues = new ArrayList<>();
}

@Override
void register(Colleague colleague) {
if (!colleagues.contains(colleague)) {
colleague.setMedium(this);
colleagues.add(colleague);
}
}

@Override
void relay(Colleague colleague) {
colleagues.forEach(c -> {
if (!c.equals(colleague)){
c.receive();
}
});
System.out.println("------------");
}
}

//具体同事类
public class ConcreteColleagueA extends Colleague{
@Override
void receive() {
System.out.println("ColleagueA receive message");
}

@Override
void send() {
System.out.println("ColleagueA send message");
mediator.relay(this);
}
}

public class ConcreteColleagueB extends Colleague{
@Override
void receive() {
System.out.println("ColleagueB receive message");
}

@Override
void send() {
System.out.println("ColleagueB send message");
mediator.relay(this);
}
}

public class ConcreteColleagueC extends Colleague{
@Override
void receive() {
System.out.println("ColleagueC receive message");
}

@Override
void send() {
System.out.println("ColleagueC send message");
mediator.relay(this);
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
ColleagueA send message
ColleagueB receive message
ColleagueC receive message
------------
ColleagueB send message
ColleagueA receive message
ColleagueC receive message
------------
ColleagueC send message
ColleagueA receive message
ColleagueB receive message
------------

在注册时

1
2
3
4
5
6
void register(Colleague colleague) {
if (!colleagues.contains(colleague)) {
colleague.setMedium(this);
colleagues.add(colleague);
}
}

每一个同事角色都知道调停者角色,而且与其它的同事角色通信的时候必须依赖调停住者才能完成,所以这里我们需要将调停者传入

我们在ConcreteMediator中定义一个List来管理同事对象(Colleague),协调各个同事角色之间的交互关系,在注册时,我们需要将每个同事对象加入

当某个同事对象(Colleague)发送信息(send)时,会去通知调停者,收到信息的用户发送消息。

1
2
3
4
void send() {
System.out.println("ColleagueB send message");
mediator.relay(this);
}

这里的调停者就是我们在register中传入的对象

Mediator模式和Facade模式的思想很相似,一个是降低系统内部的耦合度,一个是降低外部与系统的耦合度
都借用了一个’外观类’/‘调停者’来处理其中复杂的关系

具体在实战中的应用我就不多介绍了,大家感兴趣的话,可以自行了解


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!