外观模式的关键是站在客户端角度封装高频、成组、有业务含义的操作,如watchMovie(),聚焦单一职责、明确顺序依赖、收敛调用点,并预留扩展性。
在 java 中用外观模式提供简易接口,关键不是堆砌类,而是找准“谁在用”和“它真正想做什么”。外观不是给子系统加一层壳,而是站在客户端角度,把一连串必须配合的动作打包成一个语义清晰的方法。
明确外观要封装什么操作
先别急着写 Facade 类。打开你的子系统,列出客户端每次完成一个业务目标时,实际要调用哪些类、哪些方法、按什么顺序。比如家庭影院场景中,“看电影”不是单个动作,而是:开电视 → 开音响 → 调音量 → 开 DVD → 播放影片。这些步骤就是外观要封装的逻辑内核。
- 避免把所有子系统方法都暴露到外观里,只封装高频、成组、有业务含义的操作
- 如果某操作只被一个客户端调用一次,或纯属调试用途,通常不该放进外观
- 注意顺序依赖:像数据库事务中“获取连接→执行SQL→关闭资源”,顺序错就出错,这正是外观该管的事
设计外观类时聚焦职责单一
一个外观类对应一个明确的使用场景,不是“万能中转站”。比如电商系统里,不要建一个 ECommerceFacade 暴露下单、查库存、退款、对账所有功能;而应拆成 OrderFacade(专注下单流程)、RefundFacade(专注退款流程)。
- 构造器里只注入真正需要的子系统实例,不引入冗余依赖
- 方法名用动宾短语,如 watchMovie()、purchaseProduct()、generateReport(),而不是 doSomething() 或 handle()
- 方法内部不做新业务逻辑,只协调已有子系统——外观不干活,它指挥别人干活
让客户端只和外观打交道
客户端代码里,不应再出现 Television、SoundSystem、DVDPlayer 这类子系统类型。所有交互点收敛到外观类实例。
- 把子系统类设为 package-private 或默认访问权限,从源头阻止外部直接调用
- 在 Spring 等容器中,将外观类声明为 @Service 或 @Component,通过接口注入,而非 new 出来
- 测试时用真实外观+模拟子系统(Mockito),验证它是否按预期顺序调用了正确方法,而不是测子系统本身
注意边界与演进空间
外观是门面,不是牢笼。当子系统升级或新增能力时,外观应可扩展,而不是被重写。
立即学习“Java免费学习笔记(深入)”;
- 预留扩展钩子:比如 watchMovie(String movie) 可增加 watchMovie(String movie, int volume),旧调用不受影响
- 避免在外观里做复杂判断或状态管理;状态交给子系统自己维护,外观只触发行为
- 若多个外观开始共享大量协调逻辑,说明可能需要引入中介者(Mediator)或命令(Command)模式来解耦


















