1. 外观模式初探:为什么我们需要"门面"?
第一次接触外观模式时,我正面临一个典型的系统集成难题。当时需要对接三个不同厂商的支付接口,每个接口都有复杂的初始化流程和差异化的API调用方式。在业务代码中到处散落着各种SDK初始化和异常处理的代码,直到某天修改微信支付版本时引发了支付宝接口的连锁报错——这个惨痛教训让我彻底理解了外观模式的价值。
外观模式(Facade)属于结构型设计模式,它就像建筑的门面一样,为复杂的子系统提供一个统一的入口。想象你去银行办理业务:不需要知道金库怎么管理现金、后台如何清算,只需在柜台说明需求即可。这里的柜台就是金融系统的Facade。
核心价值体现在三个方面:
- 简化接口:将多个子系统接口聚合为更高级别的接口
- 降低耦合:客户端只需依赖Facade,不直接接触子系统
- 明确层次:划分系统边界,避免交叉依赖
在支付系统的重构中,我创建了PaymentFacade类,对外提供pay()和refund()两个简洁方法。内部则封装了:
- 各支付渠道SDK初始化
- 签名生成与验证
- 异常转换与重试机制
- 日志埋点与监控上报
改造后业务代码量减少60%,且支付渠道切换只需修改Facade内部实现。这个案例让我深刻体会到:"好的架构不是没有复杂度,而是把复杂度放在对的地方"。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 模式结构与实现解析
2.1 标准UML结构拆解
外观模式的经典结构包含三个关键角色:
code复制+-------------------+ +-------------------+
| Facade | | SubSystem A |
|-------------------| |-------------------|
| +operation():void |------>| +operationA1():void|
| | | +operationA2():void|
| | +-------------------+
| | ^
| | +-------------------+
| | | SubSystem B |
| | |-------------------|
| |------>| +operationB1():void|
| | | +operationB2():void|
+-------------------+ +-------------------+
Facade(外观角色):
- 知道哪些子系统负责处理请求
- 将客户端请求委派给适当的子系统
- 通常实现为具体类而非接口(与代理模式关键区别)
SubSystem(子系统角色):
- 实现具体的功能逻辑
- 不持有Facade的引用(单向依赖)
- 可以有多
