23种设计模式一中介者模式

前言

在软件开发中,我们经常遇到对象之间存在复杂交互关系的场景。当多个对象相互依赖、相互调用时,代码会变得错综复杂,维护成本急剧上升。这种情况下,**中介者模式(Mediator Pattern)**应运而生。

今天,我们就来深入探讨这个能够有效解决对象间过度耦合的设计模式。


一、中介者模式概述

1.1 什么是中介者模式?

**中介者模式**是一种行为型设计模式,它定义了一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

1.2 生活中的例子

想象一下机场塔台的工作场景:

  • 多架飞机(同事对象)需要起飞、降落、飞行
  • 如果飞机之间直接通信,需要知道其他所有飞机的位置和状态,这会造成混乱
  • 有了塔台(中介者)后,所有飞机只与塔台通信,由塔台协调调度

这就是中介者模式的精髓:通过一个中间人来管理复杂的关系网络

1.3 核心思想

用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。


二、中介者模式的结构

2.1 角色划分

中介者模式包含以下四个核心角色:

复制代码
┌─────────────────────────────────────────┐
│            Mediator(抽象中介者)         │
│  + defineColleague()                    │
│  + operation()                          │
└─────────────────────────────────────────┘
                    ▲
                    │ 继承/实现
                    │
┌─────────────────────────────────────────┐
│        ConcreteMediator(具体中介者)    │
│  - colleagueList: List<Colleague>      │
│  + addColleague()                       │
│  + operation()                          │
└─────────────────────────────────────────┘
        │ 管理         │ 管理
        │              │
┌──────────────┐  ┌──────────────┐
│ Colleague A  │  │ Colleague B  │
│  (同事对象)  │  │  (同事对象)  │
└──────────────┘  └──────────────┘

各角色职责:

  • Mediator(抽象中介者):定义同事对象到中介者对象的接口
  • ConcreteMediator(具体中介者):实现抽象中介者的方法,协调各同事对象之间的交互
  • Colleague(抽象同事类):定义同事类的接口,保存中介者对象
  • ConcreteColleague(具体同事类):实现抽象同事类的方法,需要与其他同事交互时,通过中介者完成

三、中介者模式的代码实现

3.1 场景设定

智能家电控制系统为例:

  • 空调、电视、灯光、窗帘等家电
  • 打开电视时,灯光自动调暗
  • 开启空调时,窗帘自动关闭
  • 关闭所有家电时,一键操作

3.2 抽象中介者接口

java 复制代码
/**
 * 抽象中介者接口
 */
public interface Mediator {
    /**
     * 注册同事对象
     */
    void register(Colleague colleague);
    
    /**
     * 转发消息,协调各同事对象之间的交互
     */
    void operation(String message, Colleague colleague);
}

3.3 抽象同事类

java 复制代码
/**
 * 抽象同事类
 */
public abstract class Colleague {
    protected Mediator mediator;
    
    public Colleague(Mediator mediator) {
        this.mediator = mediator;
        // 将自己注册到中介者
        mediator.register(this);
    }
    
    /**
     * 发送消息,通过中介者转发
     */
    public void send(String message) {
        mediator.operation(message, this);
    }
    
    /**
     * 接收消息,由子类实现具体逻辑
     */
    public abstract void receive(String message);
}

3.4 具体同事类

java 复制代码
/**
 * 空调
 */
public class AirConditioner extends Colleague {
    public AirConditioner(Mediator mediator) {
        super(mediator);
    }
    
    @Override
    public void receive(String message) {
        System.out.println("【空调】收到消息:" + message);
        if ("电视已开启".equals(message)) {
            System.out.println("【空调】响应:调整温度到舒适模式");
        }
    }
    
    public void turnOn() {
        System.out.println("【空调】已开启");
        send("空调已开启");
    }
}

/**
 * 电视
 */
public class Television extends Colleague {
    public Television(Mediator mediator) {
        super(mediator);
    }
    
    @Override
    public void receive(String message) {
        System.out.println("【电视】收到消息:" + message);
        if ("空调已开启".equals(message)) {
            System.out.println("【电视】响应:调低音量");
        }
    }
    
    public void turnOn() {
        System.out.println("【电视】已开启");
        send("电视已开启");
    }
}

/**
 * 灯光
 */
public class Light extends Colleague {
    public Light(Mediator mediator) {
        super(mediator);
    }
    
    @Override
    public void receive(String message) {
        System.out.println("【灯光】收到消息:" + message);
        if ("电视已开启".equals(message)) {
            System.out.println("【灯光】响应:调暗灯光");
        } else if ("空调已开启".equals(message)) {
            System.out.println("【灯光】响应:调整为暖色调");
        }
    }
}

3.5 具体中介者

java 复制代码
import java.util.ArrayList;
import java.util.List;

/**
 * 智能家居中介者
 */
public class SmartHomeMediator implements Mediator {
    private List<Colleague> colleagues = new ArrayList<>();
    
    @Override
    public void register(Colleague colleague) {
        colleagues.add(colleague);
    }
    
    @Override
    public void operation(String message, Colleague sender) {
        // 中介者协调各同事对象之间的交互
        for (Colleague colleague : colleagues) {
            // 不需要发送给自己
            if (colleague != sender) {
                colleague.receive(message);
            }
        }
    }
}

3.6 客户端调用

java 复制代码
public class Client {
    public static void main(String[] args) {
        System.out.println("========== 中介者模式测试 ==========\n");
        
        // 创建中介者
        Mediator mediator = new SmartHomeMediator();
        
        // 创建同事对象,并将中介者传入
        AirConditioner ac = new AirConditioner(mediator);
        Television tv = new Television(mediator);
        Light light = new Light(mediator);
        
        // 测试:打开电视
        System.out.println("--- 场景1:打开电视 ---");
        tv.turnOn();
        
        System.out.println("\n--- 场景2:打开空调 ---");
        ac.turnOn();
        
        System.out.println("\n========== 测试结束 ==========");
    }
}

3.7 运行结果

复制代码
========== 中介者模式测试 ==========

--- 场景1:打开电视 ---
【电视】已开启
【空调】收到消息:电视已开启
【空调】响应:调整温度到舒适模式
【灯光】收到消息:电视已开启
【灯光】响应:调暗灯光

--- 场景2:打开空调 ---
【空调】已开启
【电视】收到消息:空调已开启
【电视】响应:调低音量
【灯光】收到消息:空调已开启
【灯光】响应:调整为暖色调

========== 测试结束 ==========

四、中介者模式的优缺点

4.1 优点

优点 说明
降低耦合度 对象之间不需要显式引用,通过中介者通信
集中控制交互 将复杂的网状结构变为星形结构,易于管理
符合开闭原则 新增同事类不影响原有代码,只需扩展中介者
简化对象协议 对象之间的一对多关系转换为一对一关系

4.2 缺点

缺点 说明
中介者职责过重 随着同事类增多,中介者会变得复杂庞大
难以维护 中介者逻辑复杂时,不利于后续维护和扩展
性能开销 所有交互都通过中介者转发,可能影响性能

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

5.1 适用场景

对象之间存在复杂的网状结构

当多个对象之间存在多对多的交互关系时

希望降低对象之间的耦合度

不希望对象之间显式地相互引用

需要统一管理和协调交互

需要一个中心控制器来协调多个对象的行为

5.2 实际应用案例

  1. MVC框架中的控制器(Controller)

    • View和Model之间通过Controller交互
  2. GUI框架中的事件监听机制

    • Swing/AWT中的事件分发器
  3. 消息中间件

    • Kafka、RabbitMQ等消息队列系统
  4. 聊天室系统

    • 用户之间通过聊天服务器转发消息

六、中介者模式与其他模式的对比

6.1 中介者模式 vs 观察者模式

对比维度 中介者模式 观察者模式
目的 解耦对象之间的复杂交互 一对多的依赖关系,状态变化通知
结构 星形结构,中心化 树形/网形结构,去中心化
控制权 中介者集中控制 主题对象广播,观察者自主响应

6.2 中介者模式 vs 门面模式

对比维度 中介者模式 门面模式
目的 解耦对象间的交互 简化外部系统的调用
交互 对象之间双向交互 单向调用,外部→内部
修改性 对象之间可动态交互 外部不感知内部变化

七、总结

7.1 核心要点回顾

  • 中介者模式通过引入中介者对象,将复杂的网状结构变为简单的星形结构
  • 适用场景:对象间存在复杂交互、需要降低耦合度、需要集中控制
  • 注意点:避免中介者成为"上帝类",合理控制其职责范围

7.2 最佳实践建议

  1. 适度使用:只有在对象间关系确实复杂时才引入中介者
  2. 职责分离:可以设计多个专门的中介者,避免单一中介者过于庞大
  3. 结合其他模式:可以与观察者模式、工厂模式等结合使用

7.3 最后的话

中介者模式就像一个优秀的项目经理,他不直接参与具体工作,但通过协调各方资源,确保整个项目顺利进行。在合适的场景下使用,能让代码更加清晰、可维护。

相关推荐
郝学胜-神的一滴14 小时前
在Vibe Coding时代,学习设计模式与软件架构
人工智能·学习·设计模式·架构·软件工程
九狼14 小时前
Flutter SSE 流式响用 Dio 实现 OpenAI 兼容接口的逐 Token 输出
http·设计模式·api
郝学胜-神的一滴15 小时前
单例模式:从经典实现到Vibe Coding时代的思考
开发语言·c++·程序人生·单例模式·设计模式·多线程
J_liaty1 天前
Java设计模式全解析:23种模式的理论与实践指南
java·设计模式
资深web全栈开发1 天前
设计模式之观察者模式 (Observer Pattern)
观察者模式·设计模式
逆境不可逃1 天前
【从零入门23种设计模式03】创建型之建造者模式(简易版与导演版)
java·后端·学习·设计模式·职场和发展·建造者模式
趣魂1 天前
心跳信令通常不采用NACK机制
设计模式·软件工程·软件构建
逆境不可逃2 天前
【从零入门23种设计模式01】创建型之工厂模式(简单工厂+工厂方法+抽象工厂)
java·spring·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式·工厂模式
测试工坊2 天前
内存泄漏自动检测(下):对症下药,5 种泄漏 5 种抓法
设计模式