中介者模式和外观模式、命令模式、责任链模式有什么区别?
简化版
中介者模式解决多个对象之间的复杂协作;外观模式给复杂子系统提供统一入口;命令模式把请求封装成对象;责任链模式让请求沿处理链传递。它们都可能“多一层”,但解决的问题完全不同。
详细版
四个模式的区别可以这样看:
| 模式 | 核心意图 | 典型结构 | 关键词 |
|---|---|---|---|
| 中介者模式 | 协调多个对象交互 | Colleague -> Mediator -> Colleague | 协作、解耦、协调中心 |
| 外观模式 | 简化子系统访问 | Client -> Facade -> Subsystems | 统一入口、隐藏复杂度 |
| 命令模式 | 请求对象化 | Invoker -> Command -> Receiver | 撤销、队列、日志、异步 |
| 责任链模式 | 多处理器按链处理请求 | Handler -> Handler -> Handler | 传递、短路、顺序 |
面试里不要只说“中间加了一层”。应说明它们各自处理的变化点:中介者处理对象关系,外观处理访问复杂度,命令处理请求表达,责任链处理处理流程。
完整版教学
一、为什么这些模式容易混
因为它们在代码结构上都可能出现一个“中间对象”:
- 中介者是中间协调者;
- 外观是统一入口;
- 命令是请求对象;
- 责任链里也可能有链路管理器。
但设计模式不能只看“有没有多一层”。真正要看的是这层在解决什么问题。
二、中介者模式:处理对象关系
中介者模式关注的是对象之间的交互复杂度。
A <-> B <-> C <-> D
变成:
A \
B -> Mediator
C /
D
中介者知道多个对象,也知道它们之间的协作规则。
典型问题是:
- 多个 UI 组件互相影响;
- 多个模块彼此联动;
- 多个对象之间依赖关系混乱。
它解决的是“对象之间怎么协作”。
三、外观模式:处理子系统访问复杂度
外观模式关注的是对外提供简单入口。
class OrderFacade {
public void createOrder(OrderRequest request) {
inventoryService.lock(request);
couponService.use(request);
paymentService.pay(request);
notifyService.send(request);
}
}
客户端不需要知道内部有多少子系统,只调用 OrderFacade.createOrder()。
外观模式强调“对客户端隐藏复杂子系统”,不一定强调子系统之间互相解耦。
如果重点是简化调用入口,是外观模式;如果重点是多个对象之间互相影响并由中心协调,是中介者模式。
四、命令模式:处理请求本身
命令模式把请求封装成对象。
interface Command {
void execute();
}
这样请求就可以被:
- 排队;
- 撤销;
- 重试;
- 记录日志;
- 延迟执行;
- 异步执行。
命令模式的关注点是“请求怎么表达和管理”,不是多个对象如何互相协调。
当然,中介者内部可以使用命令对象来执行某些动作,但这只是组合,不代表两者相同。
五、责任链模式:处理请求流转
责任链模式把多个处理器串成链:
Request -> HandlerA -> HandlerB -> HandlerC
每个处理器决定:
- 自己处理;
- 继续向后传;
- 短路结束。
它适合审批流、过滤器链、校验链、Netty Pipeline 等场景。
责任链强调“请求沿链传递”,中介者强调“中心协调多个对象”。一个是链式流程,一个是中心调度。
六、四者怎么快速区分
可以用一句判断问题:
- 对象之间互相影响太乱? 用中介者思路。
- 客户端调用子系统太麻烦? 用外观思路。
- 请求要排队、撤销、重试、记录? 用命令思路。
- 请求要经过多个处理器,可能短路? 用责任链思路。
如果面试官给一个系统设计场景,不要急着报模式名,先说变化点和复杂度来源。
七、常见误区与追问
四种模式都可能处在调用中心,但方向与意图不同。Facade 主要由客户端单向进入多个子系统;Mediator 接收多个同事的事件并反向协调;Command 把1次请求对象化;责任链让请求沿 N 个处理器传递。判断时应画出运行方向,而不是只看类名含 Manager 或 Dispatcher。
| 检查维度 | 判定依据 |
|---|---|
| Mediator / Facade | 多方协调 / 简化单向入口 |
| Command / Chain | 对象化请求 / 传递请求寻找处理 |
Facade: Client->F->S;Mediator: C<->M<->C;Chain: H1->H2
记忆钩子:中介者管关系,外观管入口,命令管请求,责任链管传递。
- 误区:Facade 和 Mediator 都不能被子系统调用。 经典 Facade 通常单向;Colleague 主动通知 Mediator 正是常见流程。
- 追问:Mediator 能发送 Command 吗? 可以,中介者负责选择协作,命令负责承载具体请求。
- 误区:责任链中心化协调处理器。 链通常由每个节点决定是否传给 next,没有统一中心。
- 追问:如何区分中介者和编排服务? 两者可能重叠,应看是否主要解决同事间网状依赖。
- 追问:面试代码怎样快速识别? 查看对象引用图和一次请求的实际流向。
八、加强记忆
中介者管“对象关系”,外观管“访问入口”,命令管“请求对象”,责任链管“处理流程”。它们都可能出现中间层,但中间层的职责不同。面试时按意图区分,比按类图形状区分更稳。