Java 23 种设计模式:从踩坑到精通 | 番外:外观 vs 中介者 —— DispatcherServlet 为什么是两个模式的合体?
Java 23 种设计模式:从踩坑到精通 | 番外:外观 vs 中介者 —— DispatcherServlet 为什么是两个模式的合体?
摘要:外观模式和中介者模式都充当“中间人”角色,但外观是单向调用的“统一入口”,中介者是双向协调的“通信枢纽”。Spring MVC 的
DispatcherServlet是理解这两个模式的绝佳案例——它对外为所有 Controller 提供统一入口(外观模式),对内协调HandlerMapping、HandlerAdapter、ViewResolver等组件之间的交互(中介者模式)。本文从DispatcherServlet源码出发,结合 UML 对比、代码实现和面试高频题,帮你彻底分清这对“结构型 vs 行为型”的中间人组合。
🗺️ 本文阅读地图(3 分钟速览)
- 为什么
DispatcherServlet同时扮演“入口”和“枢纽”?- 外观 vs 中介者:一张表看懂单向简化 vs 双向协调
- UML 对比:星型结构 vs 网状扁平化
- Spring MVC 源码级分析:
doDispatch()如何体现两种模式- 面试必问:“外观和中介者有什么区别?DispatcherServlet 用了哪个?”
📖 《Java 23 种设计模式:从踩坑到精通》
开篇:系列介绍与目录 | 当前:番外 · 外观 vs 中介者
🔗 返回系列总目录
文章目录
1. 从一个“请求处理”的流程说起
在 Spring MVC 中,一个 HTTP 请求的处理流程大概是这样的:
- 浏览器发送
/order/query请求; DispatcherServlet接收请求,分发给对应的 Controller;- Controller 返回
ModelAndView,由ViewResolver解析视图; - 最终渲染 HTML 返回给浏览器。
在这个过程中,DispatcherServlet 扮演了两个截然不同的角色:
-
对客户端(浏览器)来说,它就是一个统一的“入口”——无论什么请求,客户端只与
DispatcherServlet交互,完全不知道背后有HandlerMapping、HandlerAdapter、ViewResolver等一堆组件。这体现的是外观模式。 -
对内部组件来说,它是一个“协调中心”——
HandlerMapping找到处理器后不直接调用 Controller,而是把结果交给DispatcherServlet;HandlerAdapter执行完也不直接返回视图,而是把ModelAndView交还给DispatcherServlet。所有组件之间的交互都通过DispatcherServlet中转。这体现的是中介者模式。
// DispatcherServlet 核心方法(简化版)
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 1. 外观模式:对外统一入口——无论什么请求,都走这个方法
HttpServletRequest processedRequest = checkMultipart(request);
// 2. 中介者模式:内部组件通过 DispatcherServlet 协调
Object handler = getHandler(processedRequest); // HandlerMapping → 中介者
HandlerAdapter ha = getHandlerAdapter(handler); // 中介者 → HandlerAdapter
ModelAndView mv = ha.handle(processedRequest, response, handler); // HandlerAdapter → 中介者
processDispatchResult(processedRequest, response, mappedHandler, mv); // 中介者 → ViewResolver
}
2. UML 对比:星型结构 vs 网状扁平化
2.1 外观模式 UML(星型结构)

2.2 中介者模式 UML(网状扁平化)

3. 四大核心区别
| 对比维度 | 外观模式 | 中介者模式 |
|---|---|---|
| 意图 | 提供统一的单向调用入口,简化客户端使用 | 封装对象之间的双向交互,降低耦合 |
| 通信方向 | 单向:外观 → 子系统 | 双向:同事 ↔ 中介者 ↔ 同事 |
| 子系统感知 | 子系统不知道外观的存在 | 同事类知道中介者的存在,并通过它通信 |
| 典型应用 | SLF4J、JdbcTemplate、微服务网关 |
Spring MVC DispatcherServlet(对内)、聊天室、消息中间件 |
💡 简单记忆:外观是“一键启动按钮”(单向),中介者是“中央调度台”(双向)。你按下观影按钮,外观替你操作所有设备,设备不知道外观的存在;你在聊天室发消息,中介者把消息转发给所有人,每个人都知道中介者的存在。
4. DispatcherServlet 源码分析:两个模式的完美合体
4.1 外观模式体现:统一的请求入口
无论什么请求(GET、POST、JSON、文件上传),对于客户端来说,只有一个入口——DispatcherServlet。
// DispatcherServlet 对外:统一的入口方法
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 所有请求都走这个方法,客户端无需关心内部细节
doDispatch(request, response);
}
外观特征:
- 客户端(浏览器)只知道
DispatcherServlet这一个入口; - 客户端完全不知道
HandlerMapping、HandlerAdapter、ViewResolver的存在; - 如果内部组件升级(比如换一个
ViewResolver实现),客户端代码零修改。
4.2 中介者模式体现:内部组件的协调中心
// DispatcherServlet 对内:各个组件通过 DispatcherServlet 协调
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 1. HandlerMapping 找到处理器 → 返回给中介者
Object handler = getHandler(request);
// 2. 中介者根据 handler 类型找到对应的 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(handler);
// 3. HandlerAdapter 执行处理器 → 返回 ModelAndView 给中介者
ModelAndView mv = ha.handle(request, response, handler);
// 4. 中介者调用 ViewResolver 解析视图
processDispatchResult(request, response, mappedHandler, mv);
}
中介者特征:
HandlerMapping不直接调用 Controller,而是把结果返回给DispatcherServlet;HandlerAdapter不直接返回视图,而是把ModelAndView交还给DispatcherServlet;ViewResolver从DispatcherServlet接收数据,而不是从 Controller 直接获取;- 所有组件之间不直接交互,全部通过
DispatcherServlet中转。
4.3 一张图看懂合体设计

💡 一句话总结:
DispatcherServlet对外是外观(客户端只看得到它一个入口),对内是中介者(所有组件通过它协调交互)。两者互不冲突,各司其职。
5. 面试必问 + 追问连环炮
基础必问
- 外观模式和中介者模式有什么区别?
👉 外观是单向调用简化入口,子系统不知道外观存在;中介者是双向协调交互,同事类知道中介者并依赖它。 - Spring MVC 的
DispatcherServlet用了什么模式?
👉 对外体现外观模式(统一入口),对内体现中介者模式(协调 HandlerMapping、HandlerAdapter、ViewResolver 等组件)。 - SLF4J 用了什么设计模式?
👉 外观模式。它提供统一日志接口,后端绑定 Logback、Log4j2 等实现。
面试官追问
- “
DispatcherServlet为什么需要同时用两种模式?”
👉 对外简化客户端调用(外观),对内解耦组件交互(中介者)。如果只用外观,内部组件之间会产生网状依赖;如果只用中介者,客户端需要知道内部组件的存在。两者配合才能同时解决“对外简洁”和“对内解耦”两个问题。 - “你能再举一个同时用到外观和中介者的例子吗?”
👉 微服务架构中的 API 网关。网关对外是外观——客户端只与网关交互,不知道后端服务的细节;网关对内是中介者——它协调服务发现、负载均衡、认证鉴权等组件的交互。 - “消息队列(RabbitMQ/Kafka)的 Broker 是什么模式?”
👉 中介者模式。生产者不直接发给消费者,而是通过 Broker 中转,Broker 负责路由、广播、持久化。
🎉 恭喜:如果你能立刻说出
DispatcherServlet对外是外观、对内是中介者,并理解两者的单向/双向区别,你已经掌握了“中间人”模式最核心的辨析点。
💡 延伸阅读:本文是外观模式与中介者模式的深度对比。如果你想先了解每种模式的完整原理、UML、代码实现和面试题,可以先阅读正篇——外观模式:给复杂系统装一个“一键启动” 和 中介者模式:对象关系太乱?请一位“中间人”,再回来看这篇对比,效果更佳。
🧭 《Java 23 种设计模式:从踩坑到精通》快速导航
- 开篇:系列介绍与目录
- 当前:番外 · 外观 vs 中介者 —— DispatcherServlet 为什么是两个模式的合体?(你在这里)
- 📖 延伸阅读:外观模式正篇 | 中介者模式正篇
- 创建型模式汇总
- 结构型模式汇总
- 行为型模式汇总
🔔 关注《Java 23 种设计模式:从踩坑到精通》,用 25 篇文章彻底吃透设计模式。
📦 福利预告:全系列代码及 UML 源码将在完结时统一打包开放,点击「关注」「收藏」第一时间获取。
📌 除了设计模式,我也在深挖智能物流实战(WMS、托盘调度、机器学习落地)。欢迎点击头像,看看专栏 《出版社物流WMS智能调度实战》。技术相通,思路可鉴。
更多推荐





所有评论(0)