桥接模式(Bridge):把"抽象"与"实现"拆成两个维度
更新时间:2026-08-25。本文按"先看不用模式的困境 → 再用模式重构 → 类图对比分析"的结构,论述桥接模式。可运行代码:demos/design-patterns/bridge。
一、问题场景:两个维度独立变化,继承会爆炸
形状 × 渲染器(圆形/方形 × OpenGL/DirectX)、消息 × 渠道(短信/邮件 × 即时/延迟)、协议 × 传输(TCP/UDP × 加密/明文)。抽象维度(形状)与实现维度(渲染)都要扩展,且互相独立。
二、不使用模式:继承矩阵 N×M 爆炸
cpp
// 每加一种形状 × 渲染器,都要新增子类
class CircleOpenGL : public Circle { /* GL 画圆 */ };
class CircleDirectX : public Circle { /* DX 画圆 */ };
class RectOpenGL : public Rect { /* GL 画方 */ };
class RectDirectX : public Rect { /* DX 画方 */ };
// 4 种形状 × 3 种渲染器 = 12 个类,再加维度成倍爆炸| 缺陷 | 说明 |
|---|---|
| 类爆炸 | N 种抽象 × M 种实现 = N×M 子类,乘法增长 |
| 违反 SRP/OCP | 每个子类同时承担"形状"与"渲染"两个职责 |
| 加维度=全量回归 | 新形状要补所有渲染器的实现 |
| 代码重复 | 渲染逻辑在每个形状子类里重复出现 |
不使用模式的类图

三、使用模式:抽象组合实现,两个维度独立演进
桥接模式把"抽象部分"(形状)与"实现部分"(渲染)拆成两条独立的继承链,抽象持有实现接口的引用(组合即"桥");各维度内部自由扩展,乘积关系由运行时组合完成。
cpp
// shape_bridge.h
class Renderer { // 实现维度抽象
public:
virtual void drawCircle(double r) = 0;
virtual void drawRect(double w, double h) = 0;
virtual ~Renderer() = default;
};
class OpenGLRenderer : public Renderer { /* ... */ };
class DirectXRenderer : public Renderer { /* ... */ };
class Shape { // 抽象维度
public:
explicit Shape(Renderer& r) : renderer_(r) {}
virtual void draw() = 0; // 委托给实现
virtual ~Shape() = default;
protected:
Renderer& renderer_; // 桥:组合实现抽象
};
class Circle : public Shape {
public:
Circle(Renderer& r, double radius) : Shape(r), radius_(radius) {}
void draw() override { renderer_.drawCircle(radius_); }
private:
double radius_;
};
// 组合任意形状 × 任意渲染器
OpenGLRenderer gl; Circle c(gl, 1.0); c.draw();
DirectXRenderer dx; Circle c2(dx, 2.0); c2.draw();使用模式的类图

四、类图对比与分析
| 维度 | 不使用(继承矩阵) | 使用桥接 |
|---|---|---|
| 类数量 | N×M(乘法) | N+M(加法) |
| 加新形状 | 补所有渲染器子类 | 只加一个 Shape 子类 |
| 加新渲染器 | 补所有形状子类 | 只加一个 Renderer 子类 |
| 职责 | 子类双重职责 | 抽象管形状、实现管渲染(SRP) |
| 运行时组合 | 编译期写死 | 对象组合,动态装配 |
分析结论:桥接把乘法级复杂度降为加法级,两个维度从此独立演进。代价是间接层(多一次虚调用委托)。桥接的收益与"两维度变化的概率"成正比——只有当抽象与实现确实会独立扩展时才值得。
五、适用边界
| 适用 | 不适用 |
|---|---|
| 抽象与实现两维度都预期扩展 | 只有一个维度会变化(直接继承即可) |
| 希望运行时切换实现(热切换渲染器) | 组合固定不变(桥是过度抽象) |
| 避免继承矩阵爆炸 | 类数量小,矩阵可接受 |
与策略模式的区别:桥接与策略结构相似(都持有接口引用),但关注点不同——桥接分离"抽象结构"与"实现平台"(两个维度都重要);策略分离"上下文"与"算法"(算法是单一可变点)。桥接常与抽象工厂搭配(工厂产出一族实现对象)。
一句话总结
桥接模式用"抽象持有实现引用"的组合把两个独立变化维度拆成两条继承链,类数从 N×M 降到 N+M——两维度独立扩展互不波及;只有当抽象与实现确实会各自演进时才值得这层间接。