桥接模式的核心是用组合代替继承,分离正交变化维度。抽象层定义“做什么”,实现层专注“怎么做”,通过引用动态拼装,使各维度独立扩展、互不影响。

桥接模式的核心不是让类“多做点事”,而是让它“少绑定一点”。当一个类的行为受两个或更多彼此无关的因素影响(比如“车辆类型”和“道路材质”、“消息内容”和“发送渠道”),硬用继承去覆盖所有组合,就会迅速陷入类爆炸——3种车 × 4种路 = 12个子类,加一种车就得补4个新类。桥接模式用组合代替继承,把每个维度拉出来单独演进,运行时再动态拼装。
识别两个真正独立的变化维度
关键在于判断:这两个变化是否互不干扰、各自可能新增、且没有语义强依赖?
- ✅ 合适场景:遥控器(品牌:Sony/Philips) + 功能(开关/音量/输入源)——品牌换代不影响功能逻辑,新功能也不必为每个品牌重写
- ✅ 合适场景:图形渲染(形状:圆形/矩形) + 平台(Windows GDI / Linux X11 / WebGL)——加一种新图形,不用改所有平台代码;加一个新平台,也不用重写所有图形
- ❌ 不合适场景:“用户角色”和“权限等级”如果存在严格层级约束(如管理员必须拥有全部权限),二者就不是正交变化,桥接反而增加理解成本
拆出抽象层与实现层,用引用建立桥梁
抽象层负责定义“做什么”(比如send()、drive()、render()),但不关心怎么做;实现层专注“怎么做”,只暴露统一接口。抽象层内部持有一个实现层的引用,调用全委托过去。
- 抽象类(如Vehicle)含一个Road类型的字段,构造时注入,drive()方法里调用road.getFriction()等
- 实现接口(如Road)只声明getFriction()、getNoiseLevel(),不涉及车辆逻辑
- 客户端创建时自由组合:new Bus(new AsphaltRoad()) 或 new Truck(new DirtRoad())
让每个维度可独立扩展,无需修改对方代码
新增一个维度的变体,只需添加该维度下的新类,其他维度完全不受影响。
- 要支持“石子路”,只需新增GravelRoad implements Road,所有已有车辆类(Car、Bus、Truck)立刻可用
- 要增加“电动车”,只需新增ElectricCar extends Vehicle,它自动兼容所有已有的Road实现
- 若未来需按“载重等级”再分维度,可再引入第三层(如LoadCapacity),与原有两层保持松耦合
注意组合的时机与粒度
桥接不是越早组合越好,也不是越细越好。组合应发生在有意义的抽象边界上。
- 避免在底层基础类(如Point、String)上强行桥接——它们本身不承载业务多维变化
- 组合点应对应真实业务概念:通知系统中,“消息类型”(短信/邮件/站内信)和“发送策略”(立即/延迟/重试)是合理切分点
- 运行时组合优于编译期绑定:允许配置驱动(如从JSON读取{"vehicle":"bus","road":"asphalt"}),提升灵活性











