外观模式的优缺点是什么?
简化版
外观模式的优点是简化客户端调用、降低客户端对子系统的依赖、收口复杂流程、稳定系统边界。缺点是 Facade 容易膨胀成上帝类,可能隐藏过多细节,也可能让调用方过度依赖一个粗粒度入口。
详细版
主要优点:
- 客户端调用更简单;
- 降低客户端和多个子系统的耦合;
- 统一封装复杂流程;
- 对外接口更稳定;
- 便于统一鉴权、日志、异常处理;
- 分层边界更清晰。
主要缺点:
- 外观类可能越来越大;
- 子系统能力被过度隐藏;
- 粗粒度接口不一定适合所有调用方;
- 可能形成新的中心化依赖;
- Facade 改动可能影响大量调用方。
所以外观模式适合收口复杂流程,但要按业务边界拆分,避免把所有事情都放进一个类。
完整版教学
一、优点:调用方更简单
没有外观模式时,调用方可能要写:
userService.check();
couponService.freeze();
stockService.lock();
orderService.create();
messageService.send();
用了外观模式:
orderFacade.createOrder(request);
调用方少知道很多细节,代码更干净。
二、优点:依赖关系更少
客户端原本依赖多个子系统:
Client -> A、B、C、D
引入 Facade 后:
Client -> Facade -> A、B、C、D
客户端依赖减少,子系统变化对客户端影响也更小。
三、优点:统一处理横切逻辑
Facade 可以统一处理:
- 参数校验;
- 权限判断;
- 日志记录;
- 事务边界;
- 异常转换;
- 结果聚合。
这些逻辑如果散落在多个调用方,会很难维护。
四、缺点:容易变成上帝类
如果所有流程都放到一个 Facade:
SystemFacade
createOrder()
pay()
refund()
queryUser()
generateReport()
sendMessage()
这个类会越来越大,最后没人敢改。
外观类要按业务边界拆分,而不是全系统共用一个入口。
五、缺点:隐藏细节也可能带来问题
外观模式隐藏复杂性,但有些调用方可能需要更细粒度控制。
如果 Facade 太粗,会导致:
- 参数越来越多;
- 分支越来越多;
- 特殊场景越来越难支持;
- 接口语义越来越模糊。
这时要考虑拆分多个外观接口,而不是继续加参数。
六、常见误区与追问
外观模式以减少调用方耦合换取一个新的集中变化点。原先10个客户端各自编排4个子系统,迁移后只依赖1个 Facade,子系统调整的传播范围明显缩小;但 Facade 若持续吸收规则,会成为所有变化都要修改的瓶颈。收益必须和接口粒度、依赖数量一起评估。
| 检查维度 | 判定依据 |
|---|---|
| 收益 | 客户端简单,子系统演进影响收敛 |
| 代价 | 入口可能膨胀并隐藏细粒度能力 |
心法:好的外观减少“知道多少”,坏的外观增加“负责多少”。
- 误区:引入 Facade 后耦合消失了。 耦合被集中到 Facade,并没有凭空消失。
- 追问:它如何改善可测试性? 客户端可替换一个高层接口,但 Facade 自身仍需对子系统交互做集成测试。
- 误区:统一入口一定提高性能。 串行聚合可能更慢,性能取决于缓存、并行和网络调用设计。
- 追问:什么时候缺点会超过收益? 子系统很简单、调用方只需单一接口时,额外外观层可能没有价值。
- 追问:如何防止接口膨胀? 按用例或客户端拆分多个 Facade,而不是维护一个全能入口。
七、加强记忆
外观模式的优点是简化调用、降低依赖、收口边界;缺点是容易膨胀、过度隐藏、形成中心化依赖。用得好是清晰入口,用不好就是上帝类。