定义
中介者模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介对象来简化多个对象之间的复杂交互。这种模式的目的是减少通信对象之间的直接引用,从而减少它们之间的耦合度,使得可以独立地改变它们之间的交互。
中介者模式主要涉及以下角色:
- 中介者(Mediator)接口:定义了通信的接口。
- 具体中介者(Concrete Mediator):实现中介者接口,并协调各个对象之间的交互。
- 同事类(Colleague):需要通信的对象,它们不直接交互,而是通过中介者来进行交互。
解决的问题
- 减少对象间复杂的直接交互:
- 在一个系统中,多个对象直接相互交互可能会形成复杂的网络结构。每个对象都需要知道与其交互的多个对象,这导致系统难以理解和维护。中介者模式通过引入一个中心化的中介者对象来管理这些交互,从而减少对象之间的直接通信。
- 降低耦合度:
- 当对象直接相互交互时,它们之间的耦合度增加,一个对象的改变可能影响到与之交互的多个对象。中介者模式使得对象之间减少了直接的依赖关系,每个对象只依赖于单一的中介者,从而降低了耦合度。
- 集中控制交互逻辑:
- 在没有中介者的情况下,每个对象需要独立地管理与其他对象的交互。中介者模式允许将这些交互逻辑集中到一个位置,这样交互逻辑就更容易理解和维护。
- 动态地改变交互:
- 中介者模式提供了更多的灵活性来动态改变对象间的交互。由于交互逻辑集中在中介者中,修改中介者的行为可以轻松地改变系统中对象间的交互。
使用场景
- 复杂对象间的通信:
- 当系统中有多个对象相互交互,形成复杂的网络结构时,使用中介者模式可以将这些交互集中管理,从而简化对象间的通信并减少它们之间的依赖关系。
- 减少类间耦合:
- 如果一个系统的组件紧密耦合,以至于难以对单个组件进行修改或扩展,中介者模式可以帮助解耦这些组件,使它们更容易维护和扩展。
- 集中控制交互逻辑:
- 当需要在一个地方集中管理整个应用的交互逻辑时,中介者模式提供了一种机制来集中处理所有的交互逻辑,而不是将其分散在各个对象中。
- 重新组织系统的组件交互:
- 如果需要重构一个系统,使其组件交互更加清晰和更易管理,中介者模式可以用来重组这些组件之间的交互。
示例代码
// 中介者接口
public interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者
class ChatRoom implements ChatMediator {
private List<User> users;
public ChatRoom() {
this.users = new ArrayList<>();
}
@Override
public void addUser(User user) {
this.users.add(user);
}
@Override
public void sendMessage(String msg, User user) {
for (User u : this.users) {
// 不要将消息发送给自己
if (u != user) {
u.receive(msg);
}
}
}
}
// 同事类
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator med, String name) {
this.mediator = med;
this.name = name;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
// 具体同事类
class UserImpl extends User {
public UserImpl(ChatMediator med, String name) {
super(med, name);
}
@Override
public void send(String msg) {
System.out.println(this.name + ": Sending Message=" + msg);
mediator.sendMessage(msg, this);
}
@Override
public void receive(String msg) {
System.out.println(this.name + ": Received Message:" + msg);
}
}
// 客户端
public class MediatorPatternDemo {
public static void main(String[] args) {
ChatMediator mediator = new ChatRoom();
User john = new UserImpl(mediator, "John");
User jane = new UserImpl(mediator, "Jane");
mediator.addUser(john);
mediator.addUser(jane);
john.send("Hi there!");
jane.send("Hey!");
}
}
主要符合的设计原则
- 开闭原则(Open-Closed Principle):
- 中介者模式允许系统容易地引入新的参与者(即同事类),而无需修改中介者的代码。这意味着系统对于扩展是开放的,但对于修改是封闭的。新的同事类可以被添加进系统,只需确保它们与中介者正确交互即可。
- 单一职责原则(Single Responsibility Principle):
- 在中介者模式中,中介者类承担了协调参与者之间交互的责任,而各个同事类则专注于自己的业务逻辑。这样,每个类都只有一个改变的原因,中介者负责处理组件间的通信,而各个组件负责各自的业务。
- 里氏替换原则(Liskov Substitution Principle):
- 尽管中介者模式通常不涉及继承,但是遵守此原则确保了中介者和同事类之间保持正确的关系。如果中介者或同事类有继承关系,子类应能够替换其父类而不影响系统的整体功能。
- 迪米特法则(Law of Demeter):
- 也称为“最少知识原则”,这个原则鼓励对象间的低耦合。在中介者模式中,对象不直接与许多其他对象交互,而是通过中介者进行交互,从而减少了系统中各部分的直接通信。
在JDK中的应用
- java.util.Timer:
Timer
类和任务类(如TimerTask
)之间的关系可以看作是一种中介者模式的实现。Timer
充当中介者的角色,协调不同的TimerTask
的执行。
- Java Beans和PropertyChangeListener:
- 在Java Beans框架中,
PropertyChangeSupport
类充当中介者,协调bean和监听器(如PropertyChangeListener
)之间的交互。当bean的属性发生变化时,PropertyChangeSupport
负责通知所有注册的监听器。
- 在Java Beans框架中,
- Swing事件处理机制:
- Java Swing库中的事件处理机制也反映了中介者模式的思想。例如,在Swing组件和监听器之间,
JButton
充当中介者的角色,负责管理事件(如点击事件)和相应的事件监听器。
- Java Swing库中的事件处理机制也反映了中介者模式的思想。例如,在Swing组件和监听器之间,
- java.util.concurrent.Executor:
- 在
java.util.concurrent
包中,Executor
接口实现了中介者模式。它充当了任务提交者和实际执行任务线程之间的中介者。
- 在
在Spring中的应用
- Spring事件发布-订阅机制:
- Spring的应用事件发布-订阅机制体现了中介者模式的核心理念。
ApplicationEventPublisher
充当中介者,管理事件的发布和各个ApplicationListener
的通知。这种机制允许组件在松耦合的情况下相互通信。
- Spring的应用事件发布-订阅机制体现了中介者模式的核心理念。
- Spring Web MVC的DispatcherServlet:
- 在Spring Web MVC中,
DispatcherServlet
作为中央控制器,充当中介者的角色。它处理所有的HTTP请求并将它们委派给相应的控制器,然后再将结果返回给客户端。这里的DispatcherServlet
管理控制器、视图解析器和其他相关组件之间的交互。
- 在Spring Web MVC中,
- Spring数据访问框架:
- 在Spring的数据访问框架中,比如JdbcTemplate和HibernateTemplate,模板类可以被看作是中介者,协调应用程序代码和底层数据源之间的交互。它们处理数据访问的逻辑并将结果传递给应用程序。