一、什么是中介者模式
中介者模式属于行为型设计模式,它的核心思想是:将对象之间的交互交给一个中介者对象来处理,而不是让对象之间直接通信。这样做的好处是减少了类与类之间的耦合,使得系统更加松散,便于维护和扩展。
在软件设计中,经常会遇到多个对象之间需要互相通信的场景。随着对象数量的增多,它们之间的交互关系变得越来越复杂。这时候,如何有效管理这些对象之间的依赖关系,避免过度耦合,成为了我们必须面对的问题。
在这种情况下,中介者模式(Mediator Pattern) 提供了一个优雅的解决方案。它通过引入一个中介者对象来协调多个对象之间的交互,从而减少了对象之间的直接依赖。本文将通过一个简单的示例来讲解中介者模式的应用。
二、中介者模式的结构
- Mediator(中介者接口):定义了与同事类的交互接口,通常包括注册同事对象和转发消息的方法。
- ConcreteMediator(具体中介者):实现了Mediator接口,协调所有同事对象之间的交互。
- Colleague(同事类):每个同事对象都持有一个中介者实例,通过中介者与其他同事对象进行通信。
- ConcreteColleague(具体同事类):具体的同事对象,定义了自己的行为,并通过中介者与其他同事交互。
三、示例代码
以下是一个模拟的例子,我们在其中实现了一个简单的消息传递系统,两个同事对象通过中介者交换信息。
1. 定义中介者抽象类
java
public abstract class Mediator {
public abstract void register(Colleague colleague); // 注册同事
public abstract void relay(Colleague cl); // 转发消息
}
Mediator
类定义了两个方法:
register(Colleague colleague)
:注册同事对象。relay(Colleague cl)
:转发消息。当一个同事发送请求时,调用此方法将请求传递给其他同事。
2. 实现具体中介者
java
public class ConcreteMediator extends Mediator {
private List<Colleague> colleagues = new ArrayList<Colleague>(); // 存储同事对象
@Override
public void register(Colleague colleague) {
if (!colleagues.contains(colleague)) {
colleagues.add(colleague); // 注册同事对象
colleague.setMediator(this); // 设置中介者
}
}
@Override
public void relay(Colleague cl) {
for (Colleague colleague : colleagues) {
if (!colleague.equals(cl)) { // 排除发送消息的同事
colleague.receive(); // 通知其他同事
}
}
}
}
在 ConcreteMediator
中,我们维护了一个同事列表 colleagues
。当一个同事发送消息时,relay()
方法会将消息传递给其他所有同事(不包括发送消息的同事本身)。
3. 定义同事类
java
public abstract class Colleague {
protected Mediator mediator; // 中介者对象
public void setMediator(Mediator mediator) {
this.mediator = mediator; // 设置中介者
}
public abstract void receive(); // 接收请求的方法
public abstract void send(); // 发送请求的方法
}
Colleague
类是所有同事类的基类,每个同事都需要通过中介者与其他同事交互。具体的同事类会实现 receive()
和 send()
方法。
4. 具体同事类
java
public class ConcreteColleague1 extends Colleague {
@Override
public void receive() {
System.out.println("具体同事类1收到请求");
}
@Override
public void send() {
System.out.println("具体同事类1发出请求");
mediator.relay(this); // 通过中介者通知其他同事
}
}
java
public class ConcreteColleague2 extends Colleague {
@Override
public void receive() {
System.out.println("具体同事类2收到请求");
}
@Override
public void send() {
System.out.println("具体同事类2发出请求");
mediator.relay(this); // 通过中介者通知其他同事
}
}
ConcreteColleague1
和 ConcreteColleague2
实现了 Colleague
类,并在 send()
方法中调用中介者的 relay()
方法,将消息传递给其他同事。
5. 测试类
java
public class TestMediator {
public static void main(String[] args) {
// 实例化中介者
Mediator mediator = new ConcreteMediator();
// 实例化同事
Colleague colleague1 = new ConcreteColleague1();
Colleague colleague2 = new ConcreteColleague2();
// 注册同事
mediator.register(colleague1);
mediator.register(colleague2);
// 同事1发出请求
colleague1.send();
System.out.println("-------------------------------------------------------");
// 同事2发出请求
colleague2.send();
}
}
在 TestMediator
中,我们实例化了一个中介者 ConcreteMediator
和两个同事 ConcreteColleague1
和 ConcreteColleague2
。通过 mediator.register()
方法将同事注册到中介者中,然后调用 send()
方法模拟同事之间的消息传递。
6.输出结果
具体同事类1发出请求
具体同事类2收到请求
具体同事类2发出请求
具体同事类1收到请求
从输出结果可以看到,当同事1发出请求时,同事2收到了请求;同理,当同事2发出请求时,同事1收到了请求。这是因为消息传递通过中介者进行,避免了同事之间直接通信。
四、中介者模式的优缺点
1.优点
-
降低类之间的耦合度
- 中介者模式将多个对象之间的交互集中管理,不再由每个对象直接引用其他对象。通过中介者来协调所有对象的行为,从而有效降低了对象之间的耦合度,避免了对象之间的复杂依赖关系。
- 例如,在我们的示例中,
ConcreteColleague1
和ConcreteColleague2
不再直接互相通信,它们只通过中介者ConcreteMediator
来传递消息。这使得同事之间的关系更加清晰,并且容易维护。
-
集中管理对象间的通信
- 中介者模式使得通信的管理更加集中化,所有的消息传递和请求处理都通过一个统一的中介者来处理。这减少了类与类之间的交互路径,避免了多对多的直接关系。
- 例如,如果你有很多同事对象需要互相通知,通过中介者来协调它们的通信将使得系统更加清晰和简洁。
-
简化对象间的交互逻辑
- 在没有中介者的情况下,同事对象需要彼此直接通信,可能会导致复杂的控制逻辑和依赖关系。而中介者模式通过将交互逻辑集中到中介者类中,使得每个同事对象只需要处理自己的行为和与中介者的交互,简化了整体的交互流程。
- 例如,
ConcreteColleague1
和ConcreteColleague2
只关心自己接收和发送消息,而不需要知道其他同事的存在或与它们的具体交互。
-
增强系统的可扩展性
- 如果需要增加新的同事对象,只需要创建新的同事类,并将其注册到中介者中即可,无需修改其他同事的代码。这符合开闭原则(对扩展开放,对修改关闭)。
- 例如,若要新增一个
ConcreteColleague3
类,只需要在TestMediator
中注册并实现其行为,而不需要修改ConcreteColleague1
和ConcreteColleague2
的实现。
2.缺点
-
中介者类可能过于庞大
- 由于中介者模式将所有的交互逻辑集中到一个中介者类中,随着系统的增长和同事对象的增加,
ConcreteMediator
类可能变得非常复杂和庞大。所有的交互和控制逻辑都被集中在一个类中,这可能导致中介者成为一个"上帝类",难以维护和扩展。 - 例如,当有大量同事类和它们之间复杂的交互关系时,中介者可能需要处理过多的分支逻辑,导致代码难以管理。
- 由于中介者模式将所有的交互逻辑集中到一个中介者类中,随着系统的增长和同事对象的增加,
-
违反单一职责原则(SRP)
- 中介者类的职责是协调所有同事类之间的通信,随着功能的增加,中介者类可能需要处理过多的职责,从而违反了单一职责原则(SRP)。在某些复杂场景下,单一的中介者类可能承担了过多的职责,导致其维护和扩展变得困难。
- 例如,
ConcreteMediator
类不仅需要负责注册同事,还需要处理所有同事之间的消息转发,这些行为可能来自不同的领域或模块,导致中介者类的职责过于宽泛。
-
增加了中介者的复杂性
- 中介者模式引入了中介者对象,可能会导致额外的复杂性。虽然它减少了同事对象之间的交互复杂性,但同时也带来了中介者本身的设计复杂性,特别是当系统中有多个中介者时,管理这些中介者的交互和职责也变得更加复杂。
- 例如,系统中有多个中介者时,如何划分职责、如何协调不同中介者之间的关系,都是需要考虑的问题。
-
难以处理复杂的交互逻辑
- 在一些场景中,多个同事之间的交互可能涉及到复杂的业务逻辑。如果所有的逻辑都集中在中介者类中,可能会导致业务逻辑的高度集中,难以测试和维护。特别是当业务逻辑涉及多个领域模型时,单一的中介者可能无法有效处理这些复杂的交互。
- 例如,如果每个同事类与其他同事类的交互都非常复杂,且每个同事类还需要执行额外的业务操作,那么仅靠中介者来处理这些交互,可能会使得中介者的代码变得难以管理和维护。
五、适用场景
尽管中介者模式有一些缺点,但它在以下场景中非常有效:
- 复杂的交互:当系统中有多个对象需要相互协作时,可以使用中介者模式来集中管理这些对象的交互,简化通信流程。
- 减少类之间的耦合:当多个对象之间的交互关系过于复杂且紧密时,使用中介者模式可以有效降低类与类之间的耦合度。
- 松散耦合的系统:如果系统中的多个组件需要互相协调,但又不希望它们之间有直接依赖关系时,中介者模式可以帮助实现松散耦合。
六、总结
中介者模式通过引入一个中介者来协调对象之间的交互,减少了对象之间的直接依赖,降低了系统的复杂度。它使得对象之间的交互变得更加清晰,并增强了系统的可扩展性。然而,在使用中介者模式时,我们需要注意中介者可能变得过于庞大和复杂,因此合理地设计中介者的职责和功能是非常重要的。
通过本文的示例和分析,相信你已经对中介者模式的优缺点有了更深入的理解。在实际开发中,根据具体需求来选择是否使用中介者模式,可以帮助你更加灵活地应对复杂的交互场景。