附链
你也可以在这些平台阅读本文:
定义
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
四个角色
中介者模式主要有以下四个角色:
- 抽象中介者Mediator:提供了注册同事对象与转发同事对象信息的抽象方法。
- 具体中介者Concrete Mediator:管理同事对象类,协调所有同事对象之间的交互关系。
- 抽象同事类Colleague:提供同事对象之间交互的抽象方法。
- 具体同事类Concrete Colleague:抽象同事类的实现者,与其余同事对象交互时,交由中介者对象处理。
场景示例
中介者模式在日常生活中还是比较常见的。
微信群聊就是一个很典型的例子。公司员工之间有什么事都可以通过微信群这个中介者进行多人的沟通,而不需要每次都单独一对一的找员工沟通。
打个比方,最近新冠肆虐,很多公司都延迟复工了,公司人事经理需要给所有员工发延迟复工通知。假设忽略微信群发助手功能,那公司人事经理需要一对一的告知员工延迟复工,那是不是要忙死了?
现在我们通过微信群告知来进行简单的实现。
创建抽象中介者
/**
* @author zhh
* @description 工作群类
* @date 2020-03-03 12:12
*/
public interface WorkGroup {
/**
* 添加员工
* @param staff 员工
*/
void addStaff(IStaff staff);
/**
* 发送消息
* @param staff 发送消息的员工
* @param message 消息
*/
void sendMessage(IStaff staff, String message);
}
创建具体中介者
/**
* @author zhh
* @description 微信工作群
* @date 2020-03-03 12:29
*/
public class WeChatWorkGroup implements WorkGroup {
private List<IStaff> staffList = new ArrayList<IStaff>();
public void addStaff(IStaff staff) {
if (staff != null && !staffList.contains(staff)) {
staffList.add(staff);
}
}
public void sendMessage(IStaff staff, String message) {
for (IStaff iStaff : staffList) {
// 排除自身, 给别的员工发消息
if (!staff.equals(iStaff)) {
iStaff.receiveMessage(message);
}
}
}
}
创建抽象同事类
/**
* @author zhh
* @description 员工类
* @date 2020-03-03 12:26
*/
public abstract class IStaff {
protected WorkGroup workGroup;
/**
* 姓名
*/
protected String name;
public IStaff(WorkGroup workGroup, String name) {
this.workGroup = workGroup;
this.name = name;
}
/**
* 接收消息
* @param message 消息
*/
public abstract void receiveMessage(String message);
/**
* 发送消息
* @param message 消息
*/
public abstract void sendMessage(String message);
}
创建具体同事类
/**
* @author zhh
* @description 老板
* @date 2020-03-03 12:52
*/
public class Boss extends IStaff {
public Boss(WorkGroup workGroup) {
super(workGroup, null);
// 注册至中介者对象当中
workGroup.addStaff(this);
}
@Override
public void receiveMessage(String message) {
System.out.println(String.format("老板接收到消息: %s", message));
}
@Override
public void sendMessage(String message) {
System.out.println(String.format("老板发送消息: %s", message));
workGroup.sendMessage(this, message);
}
}
/**
* @author zhh
* @description 人事经理
* @date 2020-03-03 12:49
*/
public class PersonnelManager extends IStaff {
public PersonnelManager(WorkGroup workGroup) {
super(workGroup, null);
// 注册至中介者对象当中
workGroup.addStaff(this);
}
@Override
public void receiveMessage(String message) {
System.out.println(String.format("人事经理接收到消息: %s", message));
}
@Override
public void sendMessage(String message) {
System.out.println(String.format("人事经理发送消息: %s", message));
workGroup.sendMessage(this, message);
}
}
/**
* @author zhh
* @description 普通员工
* @date 2020-03-03 12:48
*/
public class Staff extends IStaff {
public Staff(WorkGroup workGroup, String name) {
super(workGroup, name);
// 注册至中介者对象当中
workGroup.addStaff(this);
}
@Override
public void receiveMessage(String message) {
System.out.println(String.format("员工[%s]接收到消息: %s", this.name, message));
}
@Override
public void sendMessage(String message) {
System.out.println(String.format("员工[%s]发送消息: %s", this.name, message));
workGroup.sendMessage(this, message);
}
}
测试类及输出
/**
* @author zhh
* @description 测试类
* @date 2020-03-03 12:53
*/
public class Test {
public static void main(String[] args) {
// 创建中介者对象
WorkGroup weChatWorkGroup = new WeChatWorkGroup();
// 创建具体同事对象
Boss boss = new Boss(weChatWorkGroup);
PersonnelManager personnelManager = new PersonnelManager(weChatWorkGroup);
Staff staffA = new Staff(weChatWorkGroup, "海豪");
Staff staffB = new Staff(weChatWorkGroup, "亚萍");
System.out.println(">>>>>");
personnelManager.sendMessage("@所有人 由于近期新冠疫情影响,公司决定延迟复工, 具体时间另行通知, 收到请回复!");
System.out.println("<<<<<");
System.out.println();
System.out.println(">>>>>");
boss.sendMessage("疫情期间没事不要外出, 勤洗手, 戴口罩, 大家注意安全哦~");
System.out.println("<<<<<");
System.out.println();
System.out.println(">>>>>");
staffA.sendMessage("收到");
System.out.println("<<<<<");
System.out.println();
System.out.println(">>>>>");
staffB.sendMessage("收到");
System.out.println("<<<<<");
}
}
测试类的输出结果如下:
>>>>>
人事经理发送消息: @所有人 由于近期新冠疫情影响,公司决定延迟复工, 具体时间另行通知, 收到请回复!
老板接收到消息: @所有人 由于近期新冠疫情影响,公司决定延迟复工, 具体时间另行通知, 收到请回复!
员工[海豪]接收到消息: @所有人 由于近期新冠疫情影响,公司决定延迟复工, 具体时间另行通知, 收到请回复!
员工[亚萍]接收到消息: @所有人 由于近期新冠疫情影响,公司决定延迟复工, 具体时间另行通知, 收到请回复!
<<<<<
>>>>>
老板发送消息: 疫情期间没事不要外出, 勤洗手, 戴口罩, 大家注意安全哦~
人事经理接收到消息: 疫情期间没事不要外出, 勤洗手, 戴口罩, 大家注意安全哦~
员工[海豪]接收到消息: 疫情期间没事不要外出, 勤洗手, 戴口罩, 大家注意安全哦~
员工[亚萍]接收到消息: 疫情期间没事不要外出, 勤洗手, 戴口罩, 大家注意安全哦~
<<<<<
>>>>>
员工[海豪]发送消息: 收到
老板接收到消息: 收到
人事经理接收到消息: 收到
员工[亚萍]接收到消息: 收到
<<<<<
>>>>>
员工[亚萍]发送消息: 收到
老板接收到消息: 收到
人事经理接收到消息: 收到
员工[海豪]接收到消息: 收到
<<<<<
类结构图
以上示例类的结构图如下所示
总结
适用场景
- 当对象之间存在复杂的引用关系而导致依赖关系结构混乱且难以复用时。
- 交互的公共行为,当想创建一个运行于多个类之间的对象,但是又不想生成新的子类时。
优点
- 降低了对象之间的耦合性,提高了对象的复用性。
- 将对象间的一对多关联关系转变为一对一的关联关系,降低了程序的复杂度。
缺点
在某些场景中,如果设计不妥当,会使得中介者对象本身过于复杂。
参考
- 《Head First 设计模式》
- 《大话设计模式》
- 维基百科-中介者模式
- 菜鸟教程-中介者模式