说明
中介者(Mediator)模式属于行为型模式。定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。简单的说,A想跟B通信,需要中介者M来完成。
应用场景
- 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。
模式特征
角色 | 说明 | 举栗 |
---|---|---|
抽象中介者(Mediator)角色 | 它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。 | Mediator |
具体中介者(ConcreteMediator)角色 | 实现中介者接口,定义一个集合来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。 | ChatPlatform |
抽象同事类(Colleague)角色 | 定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。 | User |
具体同事类(Concrete Colleague)角色 | 是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互 | NormalUser |
代码实现
- 抽象中介者
public abstract class Mediator {
List<User> list = new ArrayList<>();//所有在聊天室里的人存这
abstract void sendToAll(String msg);//群发
abstract void senToPerson(String msg, String name);//给某个人发送消息
abstract void join(User user);//用户加入聊天室
abstract void leave(User user);//用户离开聊天室
}
- 具体中介者
public class ChatPlatform extends Mediator {
@Override
void sendToAll(String msg) {
for (User u : list) {
u.accept(msg);
}
}
@Override
void senToPerson(String msg, String name) {
for (User u : list) {
if (u.name.equals(name))
u.accept(msg);
}
}
@Override
void join(User user) {
list.add(user);
}
@Override
void leave(User user) {
list.remove(user);
}
}
- 抽象同事类
public abstract class User {
protected Mediator mediator;
String name;
//在创建对象的时候就把他的中间者传入,他要发送都是通过这个中介者来做的。
public User(String name, Mediator mediator){
this.name = name;
this.mediator = mediator;
}
abstract void sendToAll(String msg);//给所有人发消息
abstract void senToPerson(String msg, String name);//给某个人发送消息
abstract void accept(String msg);//接受消息
abstract void join();//加入聊天室
abstract void leave();//离开聊天室
}
- 具体同事类
public class NormalUser extends User {
public NormalUser(String name, Mediator mediator) {
super(name, mediator);
}
@Override
void sendToAll(String msg) {
mediator.sendToAll(msg);
}
@Override
void senToPerson(String msg, String name) {
mediator.senToPerson(msg, name);
}
@Override
void accept(String msg) {
System.out.println(this.name + "收到消息:" + msg);
}
@Override
void join() {
mediator.join(this);
}
@Override
void leave() {
mediator.leave(this);
}
}
- 客户端测试
public class Client {
public static void main(String[] args) {
Mediator chatPlatform = new ChatPlatform();
NormalUser a = new NormalUser("A", chatPlatform);
NormalUser b = new NormalUser("B", chatPlatform);
NormalUser c = new NormalUser("C", chatPlatform);
a.join();
b.join();
c.join();
System.out.println("-----------------A群发送消息------------------");
a.sendToAll("A:大家听得到吗?");
System.out.println("-----------------A给B私发消息------------------");
a.senToPerson("A:B,我只想和你说", "B");
System.out.println("-----------------B给A私发消息------------------");
b.senToPerson("B:可以,请说", "A");
System.out.println("-----------------A离开聊天室------------------");
a.leave();
System.out.println("-----------------B群发送消息------------------");
b.sendToAll("B:A能听到吗");
}
}
- 结果
-----------------A群发送消息------------------
A收到消息:A:大家听得到吗?
B收到消息:A:大家听得到吗?
C收到消息:A:大家听得到吗?
-----------------A给B私发消息------------------
B收到消息:A:B,我只想和你说
-----------------B给A私发消息------------------
A收到消息:B:可以,请说
-----------------A离开聊天室------------------
-----------------B群发送消息------------------
B收到消息:B:A能听到吗
C收到消息:B:A能听到吗
优缺点
优点
- 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
- 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合 “开闭原则”。
- 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。
缺点
在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。(也就是把具体同事类之间的交互复杂性集中到了中介者类中,结果中介者成了最复杂的类)