桥接模式用于分离正交变化维度,如通知类型与发送方式,通过组合而非继承解耦抽象层(Notifier)与实现层(MessageSender),避免N×M组合爆炸。

桥接模式不是用来“补漏”的,而是提前把系统结构搭稳,防止抽象和实现一变就牵一发动全身。关键在于识别出哪些变化是彼此独立的、未来可能各自新增的,并用组合把它们松散连起来。
找准那两个正交变化的维度
别急着写代码,先看需求里有没有两组“互不关心”的变量:
- 一组管“做什么”:比如通知类型(订单通知、退款通知、预警通知)
- 另一组管“怎么做”:比如发送方式(短信、邮件、企业微信、飞书)
- 这两组之间没有语义绑定——“订单通知”不天然属于“短信”,它也可以走邮件;“短信”也不只为“订单通知”服务
- 一旦新增一个通知类型,就得为所有渠道各写一遍;新增一个渠道,又得适配所有通知类型——这就是典型的 N × M 组合爆炸信号
划清抽象层与实现层的边界
抽象层只回答“谁来发、发什么、什么时候发”,实现层只负责“怎么连、怎么格式化、怎么投递”:
- 抽象层定义一个基类(如 Notifier),持有一个实现接口(如 MessageSender)的引用,提供统一入口(如 notify())
- 具体抽象子类(如 UrgentNotifier、DelayedNotifier)只扩展业务规则,不碰发送细节
- 实现层定义接口(如 MessageSender),声明基础动作(如 send(String content))
- 具体实现类(如 SmsSender、EmailSender)专注协议、连接池、重试逻辑等技术细节
运行时组装,而不是编译期硬绑
桥接的价值在对象创建那一刻才真正体现出来:
- new OrderNotifier(new DingTalkSender()) —— 订单通知走钉钉
- new RefundNotifier(new EmailSender()) —— 退款通知发邮件
- 甚至可以配置驱动:new NormalNotifier(senderFactory.get(config.channel))
- 抽象与实现之间没有继承关系,只有强类型组合引用,改一边不影响另一边的编译和运行
避开常见误用陷阱
桥接不是万能胶,用错地方反而让结构更乱:
- 有强语义绑定的不能拆——比如“微信小程序登录”和“手机号密码登录”是两种认证流程,不是同一抽象下的不同实现
- 抽象层别塞太多职责——如果 Notifier 开始要导出日志、生成报表、调用风控接口,说明它该被拆了
- 组合链不宜过长——Notifier → Sender → Transport → Encoder 超过三层时,建议加简单代理或埋点日志,控制间接性成本

















