外观模式的核心作用是将分散耦合的变量交互逻辑收束至统一入口,通过封装初始化顺序、协作流程与错误处理,提升可控性、复用性与隔离性;需聚焦高频固定场景,避免沦为上帝对象。

外观模式的核心作用不是改变对象变量本身,而是把原本分散、耦合、需手动协调的变量交互逻辑,收束到一个统一的入口中。它不消除子系统,也不替代变量,而是让变量的创建、组合、调用顺序变得可控、可复用、可隔离。
明确哪些变量交互逻辑值得封装
不是所有变量操作都需要外观。重点识别那些高频、固定、跨多个类、易出错的交互场景:
- 多个对象必须按特定顺序初始化(如先建连接池,再配超时策略,最后启动监听器)
- 一组变量常被一起传入不同方法(如
config、logger、validator总是一起出现) - 变量之间存在隐式依赖(比如
cacheService必须用redisClient初始化,而redisClient又依赖connectionPool) - 客户端反复写类似代码:
serviceA.doX(); serviceB.prepare(); serviceC.run(serviceA.getResult());
设计外观类时聚焦变量生命周期与协作流
外观类不是简单地把变量塞进构造函数,而是主动管理它们的存在时机、协作关系和错误边界:
- 在构造函数中完成关键依赖的注入或懒加载(避免客户端重复 new)
- 把“变量准备 → 参数组装 → 调用执行 → 结果聚合”这一整条链封装成一个方法,例如
processOrder(order, user)内部自动协调库存校验器、支付网关、通知服务等变量 - 对变量异常做统一兜底(如某个子系统不可用时,降级使用缓存变量,而非让客户端处理 NullPointerException)
- 避免暴露原始变量引用——提供只读接口或封装后的操作方法,防止客户端绕过协调逻辑直接操作底层对象
用真实交互逻辑代替伪代码示例
以一个日志上报模块为例,原始逻辑涉及三个变量紧密配合:
-
batcher:负责缓冲日志事件 -
compressor:对批次数据压缩 -
uploader:通过 HTTP 发送到远端服务
客户端若直接操作,需反复处理:batcher.add(); if (batcher.isFull()) { data = compressor.compress(batcher.flush()); uploader.send(data); }
改用外观后:
- 外观类
LogPipeline在内部持有这三个变量,并设定默认阈值与重试策略 - 对外只暴露
submit(LogEvent event)一个方法,内部自动判断是否触发压缩上传 - 变量交互细节(如压缩失败时是否丢弃批次、上传超时后是否重入队列)全部内聚在外观中,不泄漏给调用方
警惕外观类变成“上帝对象”的信号
当外观开始承担业务规则、状态管理或跨领域决策时,就偏离了本意。健康外观的标志是:
- 方法名全是动宾短语(
playVideo()、submitPayment()、startHomeMode()),不含条件分支或策略选择 - 不持有业务数据(如订单ID、用户偏好),只持有所需的子系统对象
- 新增子系统功能时,只需扩展外观方法,不修改已有方法逻辑
- 单元测试只需验证外观方法的输入输出,无需 mock 所有子系统——因为协调逻辑已收敛










