中介者模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,而且可以独立地改变它们之间的交互。属于行为型模式。
中介者模式的核心是中介者解耦系统各层级对象的直接耦合,各层次对象的对外交互由中介者转发。
中介者模式的结构:中介者模式主要包含以下4个角色。
- 抽象中介者(Mediator):中介者的接口,定义了同事对象间交互的方法。
- 具体中介者(Concrete Mediator):实现中介者接口,协调各个同事角色之间的交互关系。
- 抽象同事类(Colleague):定义同事类的接口,持有中介者对象,提供同事对象交互的抽象方法。
- 具体同事类(Concrete Colleague):是抽象同事类的具体实现,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
中介者模式的通用实现:
//抽象中介者
public abstract class Mediator {
//注册
public abstract void register(Colleague colleague);
//转发
public abstract void relay(Colleague colleague);
}
//具体中介者
public class ConcreteMediator extends Mediator{
private List<Colleague> colleagues = new ArrayList<>();
@Override
public void register(Colleague colleague) {
if(!colleagues.contains(colleague)) {
colleagues.add(colleague);
colleague.setMedium(this);
}
}
@Override
public void relay(Colleague colleague) {
for (Colleague receiver : colleagues) {
if (!receiver.equals(colleague)) {
receiver.receive();
}
}
}
}
//抽象同事类
public abstract class Colleague {
protected Mediator mediator;
public void setMedium(Mediator mediator) {
this.mediator = mediator;
}
//接收
public abstract void receive();
//发送
public abstract void send();
}
//具体同事类
public class ConcreteColleagueA extends Colleague{
@Override
public void receive() {
System.out.println("具体同事类A收到请求。");
}
@Override
public void send() {
System.out.println("具体同事类A发出请求。");
//请中介者转发
mediator.relay(this);
}
}
//具体同事类
public class ConcreteColleagueB extends Colleague{
@Override
public void receive() {
System.out.println("具体同事类B收到请求。");
}
@Override
public void send() {
System.out.println("具体同事类B发出请求。");
//请中介者转发
mediator.relay(this);
}
}
//测试类
public class MediatorTest {
public static void main(String[] args) {
Mediator mediator = new ConcreteMediator();
Colleague colleagueA = new ConcreteColleagueA();
Colleague colleagueB = new ConcreteColleagueB();
mediator.register(colleagueA);
mediator.register(colleagueB);
colleagueA.send();
System.out.println("==================================");
colleagueB.send();
}
}
中介者模式的结构图:
中介者模式的应用实例:我们采用“中介者模式”来实现 QQ 聊天,其中 QQ 服务器是“中介者”,QQ 用户是“同事”。
//中介者
public class QqServer {
private List<User> users = new ArrayList<>();
//注册
public void register(User user){
if(!users.contains(user)) {
users.add(user);
user.setServer(this);
}
}
//转发
public void relay(User user,String msg){
for (User receiver : users) {
if (!receiver.equals(user)) {
receiver.receive(user.getName(),msg);
}
}
}
}
//同事类
public class User {
private String name;
private QqServer server;
public User(String name){
this.name = name;
}
public void setServer(QqServer server){
this.server = server;
}
public String getName(){
return name;
}
public void sendMsg(String msg){
server.relay(this,msg);
}
public void receive(String name,String msg) {
System.out.println(name+":"+msg);
}
}
//测试类
public class Test {
public static void main(String[] args) {
QqServer server = new QqServer();
User zhangsan = new User("张三");
User lisi = new User("李四");
server.register(zhangsan);
server.register(lisi);
zhangsan.sendMsg("李四你好!");
System.out.println("=============================");
lisi.sendMsg("张三你好!");
}
}
中介者模式在源码中的应用:Jdk中的定时器Timer类中,schedule()方法最终调用sched()方法,sched()方法是操作一个任务队列TaskQueue,队列中的对象就是“同事”,Timer负责队列中对象的执行和交互,充当“中介者”。
中介者模式的优点:
- 类之间各司其职,符合迪米特法则。
- 降低了对象之间的耦合性,使得对象易于独立地被复用。
- 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
中介者模式的缺点:中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。
中介者模式的使用场景:
- 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时。
- 交互的公共行为,如果需要改变行为则可以增加新的中介类。