Luckylau's Blog

设计模式之调停者模式

​ 调停者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性的。这种模式提供了一个调停者类,用来充当“中心化”或“总线化”的角色,与各个对象通信,从而避免了其他对象之间的互相通信,从而降低了耦合度。

​ 生活中调停者模式的例子是相当常见的,一个是讲到调停者模式就避不开的关于同事之间沟通的例子。当我们身处一个大的团队中的时候,如果工作内容涉及许多同事,那么再互相沟通显然成本比较高。比如张三要结婚请婚假,手中的工作要暂时交接给李四、王五等五六个同事,分别跟他们单独沟通多麻烦,那么直接告知组长或经理就好了,由组长或经理协调一下工作给其他同事即可;你可能会说,沟通软件拉个群通知一下不行吗,当然可以,那这个时候,这个群就相当于一个“调停者”,任何人发送的消息都汇总到群里,其他群会员都可以收到消息。

下面我们通过上边提到的例子来看一下调停者模式如何实现:

​ 假设有一个团队有两名开发熊二、张三,有一名测试李四,有一名运维王五。他们都归一个组长管,任何人有事情,比如请假、建议或技术分享,都需要先报告给组长,由组长统一安排。下面的故事始于张三请假。

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
public abstract class TeamMember {
// 团队角色
public static final String RD = "开发人员";
public static final String QA = "测试人员";
public static final String OP = "运维人员";
// 仅与自己的组长维护引用关系
private TechLeader techLeader;
private String name;
protected String role;
public TeamMember(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setTechLeader(TechLeader techLeader) {
this.techLeader = techLeader;
}
// 向组长(调停者/中心角色)发送信息
public void reportToLeader(String message) {
techLeader.memberReport(this, message);
}
// 收到来自组长(调停者/中心角色)的消息
public void tempTask(String task) {
System.out.println("[" + role + "]" + name + "收到来自组长的安排: " + task);
}
// 无伤大雅的方法,与模式无关
public abstract void dailyWork();
1
2
3
4
5
6
7
8
9
10
public class Developer extends TeamMember {
public Developer(String name) {
super(name);
this.role = TeamMember.RD;
}
@Override
public void dailyWork() {
System.out.println("我是一个码农,我经常加班写代码,困了累了可能写出bug来。");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Operator extends TeamMember {
public Operator(String name) {
super(name);
this.role = TeamMember.OP;
}
@Override
public void dailyWork() {
System.out.println("我是一个运维,保证系统稳定运行,如果有线上bug及时回滚,话说开发人员写的程序真不稳定。");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Tester extends TeamMember {
public Tester(String name) {
super(name);
this.role = TeamMember.QA;
}
@Override
public void dailyWork() {
System.out.println("我是一名测试,我找出bug,确保代码质量。");
}
}
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
public class TechLeader {
// 维护有各个组员的引用
private List<TeamMember> members;
public TechLeader() {
members = new ArrayList<TeamMember>();
}
public void addTeamMember(TeamMember teamMember) {
members.add(teamMember);
teamMember.setTechLeader(this);
}
public void memberReport(TeamMember reporter, String message) {
if (message.contains("请假")) {
reporter.tempTask("同意!");
// 对相关人员发送消息或安排其执行操作
for (TeamMember m : members) {
if (m.role.equals(TeamMember.RD)) {
m.tempTask(reporter.getName() + "请假了,期间请接手他的开发工作。");
} else if (m.role.equals(TeamMember.QA)) {
m.tempTask(reporter.getName() + "请假了,期间请将他的bug交由其他开发人员处理。");
} else if (m.role.equals(TeamMember.OP)) {
m.tempTask(reporter.getName() + "请假了,期间请将他的线上问题交由其他开发人员处理。");
}
}
} else if (message.contains("建议")) {
} else if (message.contains("技术分享")) {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Client {
public static void main(String[] args) {
TeamMember xionger = new Developer("熊二");
TeamMember zhangsan = new Developer("张三");
TeamMember lisi = new Tester("李四");
TeamMember wangwu = new Operator("王五");
TechLeader leader = new TechLeader();
leader.addTeamMember(xionger);
leader.addTeamMember(zhangsan);
leader.addTeamMember(lisi);
leader.addTeamMember(wangwu);
zhangsan.reportToLeader("组长,世界很大,我想去看看,请假两天~");
}
}

调停者模式的优点

​ 松散耦合。调停者模式通过把多个节点对象之间的交互封装到调停者对象里面,从而使得节点对象之间松散耦合,基本上可以做到互补依赖。这样一来,节点对象就可以独立地变化和复用,而不再像以前那样“牵一处而动全身”了。
​ 集中控制交互。多个节点对象的交互,被封装在调停者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改调停者对象就可以了,当然如果是已经做好的系统,那么就扩展调停者对象,而各个节点类不需要做修改。
​ 多对多变成一对多。没有使用调停者模式的时候,节点对象之间的关系通常是多对多的,引入调停者对象以后,调停者对象和节点对象的关系通常变成双向的一对多,这会让对象的关系更容易理解和实现。
调停者模式的缺点

调停者模式的缺点:

​ 过度集中化。如果节点对象的交互非常多,而且比较复杂,当这些复杂性全部集中到调停者的时候,会导致调停者对象变得十分复杂,而且难于管理和维护。通过上边的例子也可以初见端倪,无论是请假、建议、技术分享等等所有的处理都要交给调停者。

Luckylau wechat
如果对您有价值,看官可以打赏的!