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 最后的话

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

相关推荐
he___H1 小时前
Spring中的设计模式
java·spring·设计模式
程序员小寒2 小时前
JavaScript设计模式(八):命令模式实现与应用
前端·javascript·设计模式·ecmascript·命令模式
程序员榴莲9 小时前
设计模式之GoF设计模式(单例模式
单例模式·设计模式
砍光二叉树11 小时前
【设计模式】行为型-解释器模式
设计模式·解释器模式
砍光二叉树11 小时前
【设计模式】行为型-备忘录模式
设计模式·备忘录模式
光影少年11 小时前
实现发布订阅模式
前端·javascript·设计模式
无籽西瓜a11 小时前
【西瓜带你学设计模式 | 第十一期 - 模板方法模式】模板方法模式 —— 流程骨架与钩子实现、优缺点与适用场景
java·后端·设计模式·软件工程·模板方法模式
砍光二叉树1 天前
【设计模式】行为型-中介者模式
设计模式·中介者模式
sanzk1 天前
工厂方法模式
设计模式
大数据新鸟1 天前
设计模式详解——外观模式
设计模式·外观模式