21 设计模式之中介者模式

一、什么是中介者模式

中介者模式属于行为型设计模式,它的核心思想是:将对象之间的交互交给一个中介者对象来处理,而不是让对象之间直接通信。这样做的好处是减少了类与类之间的耦合,使得系统更加松散,便于维护和扩展。

在软件设计中,经常会遇到多个对象之间需要互相通信的场景。随着对象数量的增多,它们之间的交互关系变得越来越复杂。这时候,如何有效管理这些对象之间的依赖关系,避免过度耦合,成为了我们必须面对的问题。

在这种情况下,中介者模式(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);  // 通过中介者通知其他同事
    }
}

ConcreteColleague1ConcreteColleague2 实现了 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 和两个同事 ConcreteColleague1ConcreteColleague2。通过 mediator.register() 方法将同事注册到中介者中,然后调用 send() 方法模拟同事之间的消息传递。

6.输出结果

具体同事类1发出请求

具体同事类2收到请求


具体同事类2发出请求

具体同事类1收到请求

从输出结果可以看到,当同事1发出请求时,同事2收到了请求;同理,当同事2发出请求时,同事1收到了请求。这是因为消息传递通过中介者进行,避免了同事之间直接通信。


四、中介者模式的优缺点

1.优点

  • 降低类之间的耦合度

    • 中介者模式将多个对象之间的交互集中管理,不再由每个对象直接引用其他对象。通过中介者来协调所有对象的行为,从而有效降低了对象之间的耦合度,避免了对象之间的复杂依赖关系。
    • 例如,在我们的示例中,ConcreteColleague1ConcreteColleague2 不再直接互相通信,它们只通过中介者 ConcreteMediator 来传递消息。这使得同事之间的关系更加清晰,并且容易维护。
  • 集中管理对象间的通信

    • 中介者模式使得通信的管理更加集中化,所有的消息传递和请求处理都通过一个统一的中介者来处理。这减少了类与类之间的交互路径,避免了多对多的直接关系。
    • 例如,如果你有很多同事对象需要互相通知,通过中介者来协调它们的通信将使得系统更加清晰和简洁。
  • 简化对象间的交互逻辑

    • 在没有中介者的情况下,同事对象需要彼此直接通信,可能会导致复杂的控制逻辑和依赖关系。而中介者模式通过将交互逻辑集中到中介者类中,使得每个同事对象只需要处理自己的行为和与中介者的交互,简化了整体的交互流程。
    • 例如,ConcreteColleague1ConcreteColleague2 只关心自己接收和发送消息,而不需要知道其他同事的存在或与它们的具体交互。
  • 增强系统的可扩展性

    • 如果需要增加新的同事对象,只需要创建新的同事类,并将其注册到中介者中即可,无需修改其他同事的代码。这符合开闭原则(对扩展开放,对修改关闭)。
    • 例如,若要新增一个 ConcreteColleague3 类,只需要在 TestMediator 中注册并实现其行为,而不需要修改 ConcreteColleague1ConcreteColleague2 的实现。

2.缺点

  • 中介者类可能过于庞大

    • 由于中介者模式将所有的交互逻辑集中到一个中介者类中,随着系统的增长和同事对象的增加,ConcreteMediator 类可能变得非常复杂和庞大。所有的交互和控制逻辑都被集中在一个类中,这可能导致中介者成为一个"上帝类",难以维护和扩展。
    • 例如,当有大量同事类和它们之间复杂的交互关系时,中介者可能需要处理过多的分支逻辑,导致代码难以管理。
  • 违反单一职责原则(SRP)

    • 中介者类的职责是协调所有同事类之间的通信,随着功能的增加,中介者类可能需要处理过多的职责,从而违反了单一职责原则(SRP)。在某些复杂场景下,单一的中介者类可能承担了过多的职责,导致其维护和扩展变得困难。
    • 例如,ConcreteMediator 类不仅需要负责注册同事,还需要处理所有同事之间的消息转发,这些行为可能来自不同的领域或模块,导致中介者类的职责过于宽泛。
  • 增加了中介者的复杂性

    • 中介者模式引入了中介者对象,可能会导致额外的复杂性。虽然它减少了同事对象之间的交互复杂性,但同时也带来了中介者本身的设计复杂性,特别是当系统中有多个中介者时,管理这些中介者的交互和职责也变得更加复杂。
    • 例如,系统中有多个中介者时,如何划分职责、如何协调不同中介者之间的关系,都是需要考虑的问题。
  • 难以处理复杂的交互逻辑

    • 在一些场景中,多个同事之间的交互可能涉及到复杂的业务逻辑。如果所有的逻辑都集中在中介者类中,可能会导致业务逻辑的高度集中,难以测试和维护。特别是当业务逻辑涉及多个领域模型时,单一的中介者可能无法有效处理这些复杂的交互。
    • 例如,如果每个同事类与其他同事类的交互都非常复杂,且每个同事类还需要执行额外的业务操作,那么仅靠中介者来处理这些交互,可能会使得中介者的代码变得难以管理和维护。

五、适用场景

尽管中介者模式有一些缺点,但它在以下场景中非常有效:

  • 复杂的交互:当系统中有多个对象需要相互协作时,可以使用中介者模式来集中管理这些对象的交互,简化通信流程。
  • 减少类之间的耦合:当多个对象之间的交互关系过于复杂且紧密时,使用中介者模式可以有效降低类与类之间的耦合度。
  • 松散耦合的系统:如果系统中的多个组件需要互相协调,但又不希望它们之间有直接依赖关系时,中介者模式可以帮助实现松散耦合。

六、总结

中介者模式通过引入一个中介者来协调对象之间的交互,减少了对象之间的直接依赖,降低了系统的复杂度。它使得对象之间的交互变得更加清晰,并增强了系统的可扩展性。然而,在使用中介者模式时,我们需要注意中介者可能变得过于庞大和复杂,因此合理地设计中介者的职责和功能是非常重要的。

通过本文的示例和分析,相信你已经对中介者模式的优缺点有了更深入的理解。在实际开发中,根据具体需求来选择是否使用中介者模式,可以帮助你更加灵活地应对复杂的交互场景。

相关推荐
qystca5 分钟前
洛谷 P1595 信封问题 C语言dp
算法
Yhame.6 分钟前
Java 集合框架中的 List、ArrayList 和 泛型 实例
java
coding侠客6 分钟前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘
java·spring boot·后端
委婉待续12 分钟前
java抽奖系统(八)
java·开发语言·状态模式
aaasssdddd9617 分钟前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
T1an-120 分钟前
设计模式之【观察者模式】
观察者模式·设计模式
芳菲菲其弥章22 分钟前
数据结构经典算法总复习(下卷)
数据结构·算法
我是一只来自东方的鸭.35 分钟前
1. K11504 天平[Not so Mobile,UVa839]
数据结构·b树·算法
weixin_537590451 小时前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet