Day32-02|13.2.1 表现层设计模式:组织交互逻辑并隔离界面变化
Day32-02|13.2.1 表现层设计模式:组织交互逻辑并隔离界面变化
对应教材:《系统架构设计师教程(第2版)》第13章“层次式架构设计理论与实践”13.2“表现层框架设计”中的 13.2.1“表现层设计模式”。本文面向软考高级系统架构设计师,重点学习表现层常见设计模式、适用场景、职责边界、质量属性和案例答题方法。
一、教材定位与学习目标
表现层是用户、外部系统和业务应用发生交互的入口。它负责接收输入、解释请求、组织展示、返回结果,并处理登录会话、输入校验、错误提示、页面导航和部分交互状态。由于用户界面、终端类型、交互方式和前端技术变化频繁,表现层如果直接承载业务规则、数据库访问和外部协议,很快就会变成难以维护的“巨型控制器”或“胖页面”。
表现层设计模式的价值,就是把交互职责组织成可理解、可替换、可测试的结构。模式不是必须照抄的代码模板,而是对常见设计问题的经验性解决方案。考试中需要关注的不只是 MVC 这三个字母,还要说明模型、视图、控制器之间的协作关系,识别不同模式的优缺点,并根据系统类型、团队能力、终端形态和质量属性进行选择。
今天的学习目标:
- 理解表现层与业务层、数据层的职责边界。
- 掌握 MVC、MVP、MVVM 和页面控制器等模式的思想与协作过程。
- 理解 Front Controller、Application Controller、View Helper、Presentation Model 等常见模式。
- 能够分析表现层模式对可维护性、可测试性、性能、安全和用户体验的影响。
- 能够针对企业多终端系统设计合理的表现层,并完成案例题和论文表达。
二、表现层的主要职责与边界
1. 表现层应该做什么
表现层通常负责:接收 HTTP、RPC、消息或终端事件;解析请求参数;完成格式和基础合法性校验;识别用户和会话;调用应用服务;把结果转换为页面模型、JSON、XML或其他响应格式;处理导航、分页、错误提示和交互状态;记录必要的访问审计和链路信息。
这些职责的共同特点是面向交互和表示。比如“金额字段不能为空”“日期格式必须正确”属于表现层可以做的输入校验;“用户是否有权审批该订单”“订单是否允许从待审变为通过”属于业务规则,应由应用层或领域层负责。表现层可以提前提示,但不能成为唯一的业务规则执行点,因为移动端、批处理和其他接口可能绕过页面。
2. 表现层不应该做什么
表现层不应直接决定核心业务政策,不应直接拼接 SQL,不应把数据库实体原样暴露给客户端,也不应把第三方支付、消息或文件协议扩散到所有页面。若控制器中出现大量价格计算、库存扣减、审批规则和事务控制,说明业务职责已经泄漏。
表现层也不应无条件承担所有数据聚合。对于需要调用多个业务服务的页面,可以由应用服务或专门的查询服务完成组合;表现层只负责展示结果。否则页面控制器会产生长调用链、重复聚合逻辑和难以测试的外部依赖。
三、MVC 模式
1. MVC 的基本角色
MVC 将表现层划分为 Model、View 和 Controller:
| 角色 | 主要职责 | 典型内容 |
|---|---|---|
| Model | 表示数据和业务状态,提供所需数据 | 领域对象、应用模型、展示数据 |
| View | 将模型呈现给用户 | HTML页面、模板、移动界面、响应格式 |
| Controller | 接收请求、选择用例、协调模型和视图 | 路由、参数绑定、调用应用服务 |
经典流程是:用户在视图中发起操作,控制器接收请求并调用模型,模型完成状态变化或返回数据,控制器选择视图并把模型交给视图渲染。不同技术框架对 MVC 的实现方式可能不同,有的采用控制器主动选择视图,有的由模型变化通知视图,有的把模型拆为领域模型和展示模型。
2. MVC 的优点
MVC 能够隔离界面变化和业务数据,多个视图可以复用相同模型,控制器可以统一处理路由和请求流程。它有利于团队分工:前端开发关注视图,后端开发关注模型和控制器,测试人员可以分别验证交互和业务行为。对于 Web 应用和传统企业系统,MVC 具有较好的普适性。
3. MVC 的风险
如果模型承担过多展示逻辑,或者控制器直接处理复杂业务,MVC 可能演化为“胖模型”或“胖控制器”。如果多个视图共享可变模型,还可能产生隐式联动和状态污染。实践中通常需要增加应用服务、领域服务、展示模型、查询模型和统一异常处理机制,使 MVC 与整体分层架构协调起来。
四、MVP 模式
1. 基本思想
MVP 将表现层分成 Model、View 和 Presenter。View 通常是较为被动的界面,只负责显示和转发用户事件;Presenter 负责从 View 获取输入、调用模型或应用服务、组织结果并更新 View。View 与 Presenter 通过接口协作,以便使用测试替身替换真实界面。
2. 适用场景
MVP 适合交互逻辑较多、需要脱离真实 UI 进行测试的桌面应用、移动应用和复杂 Web 页面。Presenter 可以集中处理页面流程、输入校验、加载状态、错误提示和导航决策,避免代码散落在控件事件中。
3. 优缺点
优点是界面逻辑可测试、View较薄、交互流程集中;缺点是页面较多时 Presenter 数量会增加,若没有进一步拆分,Presenter 也可能变成巨型对象。应按用例、页面职责或交互场景拆分,并避免 Presenter 直接依赖数据库和具体网络客户端。
五、MVVM 模式
1. 基本思想
MVVM 将 View 与 ViewModel 联系起来。ViewModel 为视图提供可绑定的状态、命令和展示数据,视图通过数据绑定自动反映状态变化。ViewModel 不应该依赖具体控件,而是描述页面所需的状态和行为,因此适合响应式界面和多状态交互。
2. ViewModel 的职责
ViewModel 可以维护加载中、加载成功、空数据、错误、分页和提交中的状态,暴露用户操作命令,并调用应用服务完成业务请求。它还可以把领域结果转换为用户友好的展示模型,例如把状态码转成标签、把金额格式化为显示值。但它不应替代领域模型决定业务规则。
3. 优缺点
MVVM 减少了视图中的手工更新代码,有利于复杂交互和自动化测试;但数据绑定链路隐式性较强,调试和性能分析可能更困难。双向绑定如果使用不当,可能让用户输入直接修改领域数据,绕过校验和事务边界。应明确单向数据流、命令入口和状态更新策略。
六、表现层常见设计模式
1. Front Controller(前端控制器)
前端控制器为所有请求提供统一入口,负责请求分发、认证、授权、日志、异常处理、国际化、编码和公共拦截。它避免每个页面重复实现公共逻辑。前端控制器不应承载具体业务规则,而应将请求交给命令、页面控制器或应用服务。
2. Page Controller(页面控制器)
页面控制器负责一个页面或一组紧密相关页面的请求处理,适合页面数量有限、交互相对独立的系统。它结构直观,但页面增多后可能产生大量控制器和重复逻辑,需要与前端控制器、应用服务和公共组件结合。
3. Application Controller(应用控制器)
应用控制器集中处理跨多个页面或多个请求的用例流程,例如结算流程、导入向导和多步骤审批。它可以统一导航和流程状态,避免每个页面自行决定下一步。但如果把领域规则也放入应用控制器,就会形成新的业务逻辑集中点。
4. Template View(模板视图)
模板视图使用模板和数据生成最终页面,适合服务器端渲染。模板应主要负责展示,不应嵌入复杂业务判断和数据库操作。模板引擎还需提供转义、沙箱和安全配置,防止跨站脚本和模板注入。
5. Transform View(转换视图)
转换视图把领域或应用数据转换为展示格式,例如将 XML 或对象模型转换为 HTML、JSON 或移动端响应。转换规则可复用,但要明确字段映射、空值、敏感字段和版本兼容。
6. Two-Step View(两步视图)
两步视图先生成与具体外观无关的逻辑页面,再由第二步套用布局、主题和终端样式。它有助于统一网站布局和多终端适配,适合大型门户和需要统一视觉规范的系统。代价是渲染链路更长,调试需要同时理解逻辑视图和具体视图。
7. Presentation Model(展示模型)
展示模型把页面所需状态和行为从视图中提取出来,视图只负责呈现。它适合复杂表单、可编辑列表和多状态页面。展示模型可以包含格式化值、校验结果、按钮是否可用和页面状态,但核心业务判断仍应由业务层确认。
七、模式选择与组合
实际系统通常不是只选择一种模式,而是组合使用:前端控制器统一处理公共请求,页面控制器或应用控制器组织用例;后端采用 MVC 的分层思想,前端复杂页面采用 MVVM;领域模型和应用服务负责核心业务,展示模型负责终端适配。
模式选择可以依据以下因素:
| 影响因素 | 更适合的考虑 |
|---|---|
| 页面交互简单、服务器渲染 | MVC + 页面控制器 + 模板视图 |
| 交互流程复杂、需要单元测试 | MVP 或展示模型 |
| 响应式界面、状态变化频繁 | MVVM、单向数据流 |
| 多入口共用认证和审计 | Front Controller |
| 多步骤跨页面业务流程 | Application Controller 或流程服务 |
| 多终端共享业务能力 | 应用服务 + 各端独立表现模型 |
选择时还要考虑团队熟悉程度、系统生命周期、性能、可观测性和安全要求。不要因为框架默认使用 MVC,就把所有业务逻辑塞进 Controller;也不要为了追求“纯粹模式”给简单页面增加过多抽象。
八、表现层的质量属性设计
1. 可维护性与可测试性
通过控制器薄化、业务规则集中、视图无业务逻辑、展示模型隔离和依赖注入,可以降低修改成本。测试应覆盖请求路由、参数校验、权限、状态转换、错误展示和多终端适配。表现层测试不能代替领域层测试,关键业务规则应在更靠近业务的层次独立验证。
2. 性能与体验
表现层性能不仅是页面加载速度,还包括首屏时间、交互反馈、接口并发、数据传输量和失败恢复。可以采用分页、缓存、异步加载、批量接口、压缩、静态资源优化和骨架屏,但不能为了前端体验而绕过服务权限或直接访问数据库。复杂页面应明确哪些数据必须同步返回,哪些可以延迟加载。
3. 安全
表现层负责输入校验、输出编码、CSRF防护、会话管理、权限展示和敏感信息隐藏,但后端仍必须再次验证。按钮隐藏不等于授权。对于多租户和多组织系统,应在服务层依据租户、组织、角色和数据范围进行最终控制。日志中不要记录完整密码、令牌和不必要的患者或财务敏感信息。
4. 可访问性与兼容性
面向公众或多样用户时,应考虑键盘操作、屏幕阅读器、颜色对比度、错误提示和不同终端适配。表现层模式要允许展示策略变化,而不把所有内容写死在控制器中。接口还要处理时区、语言、数字格式和字符编码。
九、案例分析:企业差旅审批平台表现层设计
某企业差旅平台需要支持员工 Web 端、移动端和管理人员大屏。主要功能包括差旅申请、预算校验、逐级审批、行程调整、费用报销和消息提醒。原系统把审批规则、数据库查询和页面跳转全部写在 JSP 页面和控制器中,导致移动端难以复用,政策变化时需要修改大量页面。
1. 设计目标
目标是统一业务入口和权限控制,复用差旅领域能力,同时允许不同终端采用不同交互体验。核心质量属性包括审批规则一致、页面响应及时、移动端可用、操作可追踪和策略变更影响可控。
2. 架构方案
采用前端控制器统一完成认证、请求关联ID、异常处理和审计;Web端使用 MVC 与模板视图,移动端使用 MVVM 和展示模型,大屏使用专用查询模型。各终端通过应用服务调用差旅申请、预算校验、审批和报销用例。领域层集中差旅政策、额度和审批状态规则;通知采用异步消息,表现层只展示通知状态。
3. 交互流程
员工提交申请后,View 或 ViewModel 只收集表单数据并调用申请服务;服务层执行必填、预算、权限和政策校验;成功后返回申请编号和当前状态;审批页面根据展示模型决定按钮状态,但审批动作仍由应用服务再次校验权限和状态;消息到达后,页面通过查询或推送更新状态。
4. 关键风险与措施
为了避免不同终端规则不一致,所有核心校验集中在服务和领域层。为了避免复杂页面调用过多接口,设计聚合查询服务,同时设置权限过滤和超时。为了处理移动端网络不稳定,提交请求使用幂等键并返回可查询状态。为了方便政策变化,把展示提示和部分表单配置外置,但不把核心政策仅放在前端。
5. 验证指标
通过新终端接入周期、规则重复率、审批接口错误率、页面首屏时间、移动端提交成功率、重复申请数量、权限缺陷数和异常操作追踪覆盖率评价架构效果。
十、综合知识练习与详细答案
练习一:单项选择
下列关于表现层设计的说法正确的是( )。
A. 隐藏页面按钮即可完成权限控制 B. 控制器应直接访问数据库以减少层次 C. 表现层可以进行输入校验,但核心业务规则必须由业务层再次保证 D. MVC要求所有系统都必须严格拆成三个独立进程
答案:C。前端校验用于改善体验,不能代替服务端授权和业务规则;控制器直接访问数据库会破坏分层;MVC是逻辑模式,不要求三个独立进程。
练习二:多项选择
Front Controller适合承担( )。
A. 统一认证 B. 请求分发 C. 公共异常处理 D. 具体订单价格计算 E. 访问日志
答案:A、B、C、E。订单价格计算属于业务规则,应由应用层或领域层承担。
练习三:案例题
某移动应用采用 MVVM。开发人员把“用户是否可以审批”“订单是否允许提交”等逻辑全部放入 ViewModel,以便页面按钮及时变化。请分析该方案的问题并给出改进措施。
参考答案:ViewModel可以根据服务返回的权限和状态决定展示状态,但不能成为唯一业务规则执行点。若核心规则只放在ViewModel,Web、批处理和其他客户端可能绕过;多个ViewModel还可能产生规则重复和不一致。应把核心权限、状态转换和业务不变量放入应用服务或领域层,ViewModel只负责调用服务、维护页面状态、格式化展示和提前提示;服务端必须再次校验身份、权限、当前状态和业务约束;通过展示模型返回允许操作、原因和状态,减少前端重复推断;为服务规则建立独立测试,为ViewModel建立交互和状态测试。
十一、案例题答题模板
遇到表现层设计题,可以按以下顺序回答:
- 明确终端、用户角色、交互复杂度和关键质量属性。
- 划分表现层职责,说明哪些逻辑由应用层、领域层和数据层负责。
- 根据场景选择 MVC、MVP、MVVM、前端控制器、展示模型等模式。
- 描述请求进入、参数校验、权限验证、服务调用、结果转换和异常处理流程。
- 说明多终端复用方式、状态管理、接口版本、幂等和可观测性。
- 强调安全控制不能只依赖页面,核心规则必须在服务端执行。
- 给出迁移步骤和指标,证明架构改善了维护、测试、性能或体验。
十二、论文写作素材
开头素材
“随着企业业务从单一 Web 端扩展到移动端和管理大屏,原有表现层中页面、业务规则和数据访问高度耦合,导致终端复用困难、策略变更影响范围大、测试成本高。为解决上述问题,我参与了表现层架构改造,采用前端控制器统一处理公共请求,并结合 MVC、MVVM 和展示模型组织不同终端的交互逻辑。”
正文素材
可以从三方面展开:第一,说明如何划分视图、控制器、展示模型、应用服务和领域规则,避免“胖控制器”;第二,说明根据 Web、移动端和大屏特点选择 MVC、MVVM、查询模型和异步交互,并处理加载、分页、错误和网络不稳定;第三,说明认证、授权、输出编码、审计、日志脱敏和服务端二次校验如何贯穿表现层设计。要写出实际权衡,例如复杂页面采用专用聚合查询提升体验,但仍通过服务层控制数据范围。
结尾素材
“实践表明,表现层设计模式的目的不是追求模式数量,而是把交互变化与业务规则、数据访问和基础设施隔离开。只有在清晰职责边界的基础上选择合适模式,并通过服务端规则、自动化测试和运行指标验证,才能同时获得良好的用户体验和长期可维护性。”
十三、今日复盘
本节的核心结论是:表现层负责交互与呈现,应用层负责用例编排,领域层负责业务规则;设计模式用于组织协作,不应成为业务职责泄漏的借口。
请完成以下复盘:
- MVC、MVP 和 MVVM 的主要差异是什么?
- 为什么隐藏按钮不能代替权限控制?
- Front Controller 和 Application Controller 分别解决什么问题?
- 什么时候应采用展示模型或专用查询模型?
- 如何避免 ViewModel 或 Controller 变成新的巨型对象?
- 表现层改造应使用哪些指标验证效果?
请以一个多终端业务系统为例,画出“终端—表现模式—应用服务—领域规则—数据访问”的调用关系,并标出认证、授权、异常、日志和状态管理的位置。能够完成这一练习,就掌握了 13.2.1 在综合知识、案例分析和论文中的主要答题能力。