第14章 Web表现模式
分离请求处理、导航、模型和HTML生成的不同变化轴。
学习目标
- 能区分 MVC、Page Controller、Front Controller、Application Controller 与三种视图变换的职责
- 能用 TypeScript 把订单请求映射为可测试的 View Model,并隔离导航与模板输出
- 能根据路由共享、跨页面流程、视图变体和模板安全要求选择 Web 表示模式
为什么第14章 Web表现模式值得单独学习
第14章 Web表现模式的核心不是把框架目录换成另一套类名,而是把请求处理、导航、模型调用与 HTML 生成拆成不同的变化轴。订单后台可能同时有列表、详情、审批和导出;如果控制器既保存流程状态又拼 HTML,模板又直接访问数据库,一次路由或字段变化就会穿过整个应用。
↡把请求路由、输入校验、应用模型调用和输出选择连接起来的 Web 入口边界;它不应直接拥有持久化和核心业务规则。是请求变化与业务变化之间的隔离层。本页以 2024 年中文版公开目录限定第14章的范围,并依据 Martin Fowler 的作者图书页和模式目录独立重写;目录只决定要讲什么,案例、实验、判断题和答案均为本课程原创。
先建立直觉:问题、机制与代价
↡为单个页面或用例提供输入处理、模型调用和响应选择的控制器,适合页面边界清晰且共享流程较少的场景。适合把局部变化留在局部。
↡为多个请求提供统一入口,集中认证、路由、错误处理和通用上下文,再把请求分发给具体用例的控制器。减少共享基础设施重复,但不能因此吞掉所有页面逻辑。
↡专门封装跨页面导航和应用流程状态的协调对象,例如审批向导和多步结算流程。则拥有流程导航,不拥有每个页面的展示细节。
↡把模型数据按模板占位符生成输出的视图组件,不应直接执行数据库访问或改变领域状态。适合稳定页面结构;Transform View 把模型转换为另一种输出,Two Step View 把内容与全局布局分成两步。选择要由路由共享、流程状态、视图变体和转义安全的证据推动,而不是由框架默认值推动。
对第14章 Web表现模式,优先比较的替代路线是:页面边界局部时采用 Page Controller,认证和错误处理共享时采用 Front Controller,跨页面流程复杂时采用 Application Controller,输出格式变化时采用 Template View、Transform View 或 Two Step View。若实验只能显示一页 HTML,不能说明导航、输入校验和模板安全,就不能据此选择模式。
目录单元到教学证据
第14章 Web表现模式
第14章 Web表现模式要求把“HTTP 请求如何变成安全且可导航的响应”变成可观察的架构决定:先标出路由、控制器、应用模型、视图与导航状态的所有者,再用订单后台多视图的路由测试、流程测试和输出快照验证决定。只有模板替换不会重写业务和导航,表示模式才真正隔离了变化。
专属代码案例:订单审批后台
把订单审批后台切成“HTTP 请求 → Front/Page Controller → 应用流程 → View Model → Template/Transform View”五个观察点。第14章 Web表现模式的设计草案必须写出谁拥有状态、谁作出业务决定、失败怎样传播,以及路由、输入校验、导航、模板转义和视图复用中哪个指标最先提示当前方案不再适用。
设计记录采用五个可换行字段:单元键为 poeaa24-chapter-14-web-presentation-patterns;模式族为 web;裁决是“共享基础设施集中,页面输入局部,跨页状态独立,视图只消费已转义的 View Model”;观测项包括路由、输入校验、导航、模板转义、视图复用;拒绝条件是“模板直接查询数据库或控制器同时持有流程、业务规则和 HTML 字符串”。
先预测:订单审批从“详情”进入“确认”再进入“完成”,哪些状态属于 Application Controller,哪些内容属于 View?先写下导航、模型和模板边界,再阅读实现;验证时要能说明同一审批结果如何转换为 HTML 与 CSV,而不会重复权限和金额规则。
type ApprovalRequest = {
userId: string;
orderId: string;
action: "approve" | "reject";
};
type ApprovalViewModel = {
heading: string;
nextPath: string;
notice: string;
};
interface ApprovalApplication {
approve(
userId: string,
orderId: string,
): "approved" | "forbidden" | "missing";
reject(userId: string, orderId: string): "rejected" | "forbidden" | "missing";
}
class ApprovalPageController {
constructor(private readonly application: ApprovalApplication) {}
handle(request: ApprovalRequest): ApprovalViewModel {
const result =
request.action === "approve"
? this.application.approve(request.userId, request.orderId)
: this.application.reject(request.userId, request.orderId);
if (result === "forbidden") {
return {
heading: "Not allowed",
nextPath: "/orders",
notice: "权限不足",
};
}
if (result === "missing") {
return {
heading: "Order not found",
nextPath: "/orders",
notice: "订单不存在",
};
}
return {
heading: "Approval updated",
nextPath: `/orders/${request.orderId}`,
notice: result === "approved" ? "订单已批准" : "订单已拒绝",
};
}
}这段代码让 Page Controller 负责输入和响应模型,让应用层负责审批规则,让视图只消费 ApprovalViewModel。真实 Front Controller 可以在更外层统一认证、路由和错误记录;Template View 或 Transform View 再把同一 View Model 输出成 HTML 或 CSV,不能把用户输入直接拼入 HTML。
Web 表示模式职责矩阵
控制器组解决请求路由和流程控制,视图组解决模型到输出的转换,MVC 负责把 Model、View、Controller 的职责放在可替换边界上。下面的矩阵覆盖七种模式及其核心职责。
矩阵不是“每个项目都要用七个模式”的清单;它用于记录变化轴,帮助团队拒绝不必要的共享入口、隐式导航和模板业务逻辑。
Web 流程选择图
先看共享认证、路由和错误处理,再看是否存在跨页面流程,最后看是否存在多个输出格式。每次集中化都要给出减少重复或保护状态的证据;没有证据时保持 Page Controller 和简单 Template View。
选择与拒绝矩阵
| 评审问题 | 选择 Web 表示模式的证据 | 应拒绝当前方案的信号 |
|---|---|---|
| 路由 | 页面与共享入口的边界可测试 | 一个巨型入口包含所有页面业务分支 |
| 流程 | Application Controller 明确拥有跨页状态 | 控制器或模板用隐式变量猜测下一步 |
| 输出 | View Model 可被 HTML、CSV 或布局复用 | 每个模板复制金额、权限和状态规则 |
| 安全 | 输入校验、转义和错误路径有专门测试 | 用户输入直接进入 HTML 或 SQL |
常见误区
可验证练习
练习
本组练习覆盖第14章 Web表现模式,并要求把路由、输入校验、导航、模板转义和视图复用映射到订单后台多视图。
问题 1:选择入口。 多个页面共享认证、错误处理和路由,但每个页面的业务用例不同,应该如何拆分?
问题 2:处理跨页流程。 订单审批需要详情、确认和完成三个步骤,下一步不能由客户端任意跳过,状态应由谁拥有?
问题 3:复用输出。 同一审批结果需要 HTML 页面和 CSV 下载,如何避免视图复制规则?
名词解释
名词解释
本章出现的专业名词,用大白话再讲一遍。
- Page Controller
为单个页面或用例提供输入处理、模型调用和响应选择的局部控制器。
- Front Controller
为多个请求提供统一入口,集中认证、路由、错误处理和通用上下文的控制器。
- Application Controller
封装跨页面导航和应用流程状态的协调对象,不拥有每个页面的展示细节。
- Template View
使用模板占位符把模型数据生成输出的视图组件,不直接访问数据库或改变领域状态。
本章小结
掌握第14章 Web表现模式的标志不是记住七个模式名称,而是能在订单审批后台中解释“HTTP 请求 → 控制器 → 应用流程 → View Model → Template/Transform View”的责任链。学习者应利用路由、输入校验、导航、模板转义和视图复用作出可证伪的选择,并在巨型入口、模板业务逻辑或客户端控制流程时明确拒绝当前实现。
前后导航
来源与改写范围
- Martin Fowler 作者图书页:核对全书主题、教程与模式参考结构。
- Martin Fowler 模式目录:核对模式名称、所属模式族和作者公开摘要。
- Pearson 出版社页面:交叉核对英文版出版信息与目录范围。