Bootstrap

【设计模式】行为型-中介者模式

中介者模式如同一幅无形的画卷,细腻地编织着各个对象间错综复杂的交流,将混沌的线条渲染成和谐的画面。

一、飞机控制系统

场景假设:我们有一个飞机控制系统,其中包括飞机、塔台和地面服务。

class Airplane {
    private ControlTower tower;
    private GroundService groundService;

    // Airplane 需要知道 ControlTower 和 GroundService
    public Airplane(ControlTower tower, GroundService groundService) {
        this.tower = tower;
        this.groundService = groundService;
    }

    public void requestLanding() {
        // 需要直接与 ControlTower 通信
        tower.grantLandingPermission();
    }

    public void requestBaggageService() {
        // 需要直接与 GroundService 通信
        groundService.provideBaggageService();
    }
}

class ControlTower {
    // ...
}

class GroundService {
    // ...
}

在上面的飞机控制系统中 Airplane 需要直接与 ControlTower 和 GroundService 通信。如果我们有更多的组件,并且它们都需要相互通信,那么代码将变得非常复杂,每个组件都需要知道其他所有组件。

二、中介者模式

中介者模式(Mediator Pattern)是一种行为型设计模式,旨在减少对象之间的直接通信,而是通过一个中介对象来协调各对象之间的交互。它促进了对象之间的松耦合,使得对象之间的通信更加灵活、可复用。
在中介者模式中,通常会有一个中介者(Mediator)对象,它封装了对象之间的交互逻辑。对象之间不再直接相互引用和调用,而是通过向中介者发送消息来与其他对象通信。这种方式将复杂的交互逻辑集中管理,有助于简化对象之间的关系,提高系统的可维护性和扩展性。

三、中介者模式的核心组件

中介者模式主要包含以下几个核心组件:

  1. 中介者(Mediator):这是一个接口,它定义了各个组件(也称为同事)之间通信的协议。中介者知道所有的同事,并决定如何和何时与它们进行通信。
  2. 具体中介者(Concrete Mediator):这是实现中介者接口的类。具体中介者知道所有的同事,并实现了在同事之间进行通信的逻辑。
  3. 同事(Colleague):这些是需要相互通信的对象。每个同事都知道它的中介者,并且只与它的中介者通信,而不是直接与其他同事通信。

在这里插入图片描述

在这个类图中:

  • Mediator 是一个接口,定义了 send 方法,用于在同事之间发送消息。
  • ConcreteMediatorMediator 的一个具体实现。它维护了一个 Colleague 对象的列表,并实现了 addColleague 方法来添加新的同事。
  • Colleague 是一个接口,定义了 sendreceive 方法,用于发送和接收消息。
  • ConcreteColleagueColleague 的一个具体实现。它有一个 name 属性来标识自己,和一个 mediator 属性来引用它的中介者。

四、运用中介者模式

场景假设:我们需要开发一个飞机控制系统,其中包括飞机、塔台和地面服务。但是飞机、塔台以及地面服务之间不直接通信,而是通过一个中介进行信息交换。

  1. 定义中介者接口:首先,我们需要定义一个中介者接口,该接口定义了各个组件(也称为同事)之间通信的协议。

    // 中介者接口,定义了在同事之间发送消息的方法
    interface Mediator {
        void send(String message, Component component);
    }
    
  2. 定义同事接口:我们需要定义一个同事接口,该接口定义了同事需要实现的方法。

    // 同事接口,定义了发送和接收消息的方法
    interface Component {
        void send(String message);
        void receive(String message);
    }
    
  3. 创建具体中介者:然后,我们创建一个具体的中介者类,该类实现了中介者接口。具体中介者知道所有的同事,并实现了在同事之间进行通信的逻辑。

    // 具体中介者类,实现了中介者接口
    class ConcreteMediator implements Mediator {
        // 维护一个同事对象的列表
        private List<Component> components;
    
        public ConcreteMediator() {
            this.components = new ArrayList<>();
        }
    
        // 添加同事到列表中
        public void addComponent(Component component) {
            components.add(component);
        }
    
        // 发送消息给所有其他同事
        @Override
        public void send(String message, Component originator) {
            for (Component component : components) {
                // 不给发送消息的同事发送消息
                if (component != originator) {
                    component.receive(message);
                }
            }
        }
    }
    
  4. 创建具体同事:然后,我们创建具体的同事类,这些类实现了同事接口。每个同事都知道它的中介者,并且只与它的中介者通信,而不是直接与其他同事通信。

    // 具体同事类,实现了同事接口
    class ConcreteComponent implements Component {
        // 同事的名字
        private String name;
        // 同事知道它的中介者
        private Mediator mediator;
    
        public ConcreteComponent(String name, Mediator mediator) {
            this.name = name;
            this.mediator = mediator;
        }
    
        // 发送消息
        @Override
        public void send(String message) {
            System.out.println(this.name + " sends: " + message);
            mediator.send(message, this);
        }
    
        // 接收消息
        @Override
        public void receive(String message) {
            System.out.println(this.name + " receives: " + message);
        }
    }
    
  5. 用中介者模式:最后,我们可以使用中介者模式来简化组件之间的通信。

    // 使用中介者模式
    public static void main(String[] args) {
        // 创建一个具体的中介者
        Mediator mediator = new ConcreteMediator();
    
        // 创建具体的同事
        Component airplane = new ConcreteComponent("Airplane", mediator);
        Component controlTower = new ConcreteComponent("ControlTower", mediator);
        Component groundService = new ConcreteComponent("GroundService", mediator);
    
        // 将同事添加到中介者的列表中
        mediator.addComponent(airplane);
        mediator.addComponent(controlTower);
        mediator.addComponent(groundService);
    
        // 同事通过中介者发送和接收消息
        airplane.send("Requesting landing permission.");
        controlTower.send("Landing permission granted.");
        groundService.send("Ready for baggage service.");
    }
    

五、中介者模式的应用场景

中介者模式通常应用在以下几种场景中:

  1. 复杂的通信:当对象之间的通信变得非常复杂,以至于难以理解和维护时,可以使用中介者模式。中介者模式可以将复杂的通信过程简化为星型通信,每个对象只需要与中介者通信,而不需要直接与其他对象通信。
  2. 解耦对象:当希望解耦一组对象,使它们不直接相互引用时,可以使用中介者模式。通过引入中介者,每个对象都只需要知道中介者,而不需要知道其他对象。
  3. 动态的行为:当需要在运行时动态地改变对象之间的交互行为时,可以使用中介者模式。通过改变中介者来改变对象之间的交互行为。

以下是一些具体的应用场景:

  1. 图形用户界面(GUI):在复杂的 GUI 中,各种控件(如按钮、文本框、列表框等)之间可能需要进行复杂的通信。通过引入一个中介者,我们可以将这些控件解耦,使它们只需要与中介者通信。
  2. 聊天室:在聊天室中,每个用户都需要与其他所有用户通信。通过引入一个中介者(聊天服务器),我们可以将用户解耦,使每个用户只需要与中介者通信。
  3. 航空交通控制系统:在航空交通控制系统中,飞机、塔台和地面服务等都需要进行复杂的通信。通过引入一个中介者,我们可以将这些组件解耦,使它们只需要与中介者通信。

六、小结

中介者模式是一种强大而优雅的设计模式,能够有效地简化和管理复杂系统中对象之间的交互关系。通过合理运用中介者模式,我们可以提高代码的可读性、可维护性和扩展性,使系统设计更加优雅和灵活。

推荐阅读

  1. 深入探究 Spring Boot Starter:从概念到实践
  2. 深入理解 Java 中的 volatile 关键字
  3. OAuth 2.0:现代应用程序的授权标准
  4. Spring 三级缓存
  5. 深入了解 MyBatis 插件:定制化你的持久层框架
;