设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用
🔄 回顾 Day 12:装饰器模式小结
在 Day 12 中,我们学习了装饰器模式(Decorator Pattern):
- 强调在不改变原类结构的前提下,动态为对象增强功能。
- 通过“包装对象”实现运行时组合,支持功能增强、职责扩展。
今天我们进入结构型设计模式中的另一颗明星——桥接模式(Bridge Pattern)。
桥接模式的核心哲学是:将“抽象”与“实现”解耦,使它们可以独立变化。
一、桥接模式的核心动机
✅ 为什么要桥接?
当我们遇到一个对象,它需要同时支持两个(或多个)维度的变化:
- 图形:图形类型(圆、矩形) × 渲染方式(OpenGL、Vulkan)
- 消息:发送渠道(邮件、短信) × 消息类型(普通、加密)
如果使用继承会怎样?
→ CircleOpenGL
→ CircleVulkan
→ RectangleOpenGL
→ RectangleVulkan
会导致类爆炸!每加一个维度,都要组合多个子类。
桥接模式解决的正是:多维变化下,避免子类组合爆炸,将每个维度封装为独立模块,通过桥接连接。
二、结构图(UML)
+---------------------+ +----------------------+
| Abstraction | | Implementor |
+---------------------+ +----------------------+
| +operation() | | +implOperation() |
| - impl: Implementor* | +----------------------+
+---------------------+ /\/\ ||/ \ +----------------------+
+--------------------+ | ConcreteImplementorA |
| RefinedAbstraction | +----------------------+
+--------------------+ | +implOperation() |+----------------------+
三、角色说明
角色 | 职责说明 |
---|---|
Abstraction | 抽象接口,定义面向客户端的方法 |
Implementor | 实现接口,定义基础操作,供 Abstraction 使用 |
RefinedAbstraction | 扩展的抽象,具体调用 Implementor 的接口 |
ConcreteImplementorX | 实际实现类 |
四、C++ 实现:图形渲染系统(图形 × 渲染方式)
✅ 实现接口(Implementor)
class IRenderEngine {
public:virtual void renderCircle(float x, float y, float r) = 0;virtual ~IRenderEngine() = default;
};
✅ OpenGL/Vulkan 渲染实现
class OpenGLRenderer : public IRenderEngine {
public:void renderCircle(float x, float y, float r) override {std::cout << "OpenGL 渲染圆: (" << x << ", " << y << ") r=" << r << std::endl;}
};class VulkanRenderer : public IRenderEngine {
public:void renderCircle(float x, float y, float r) override {std::cout << "Vulkan 渲染圆: (" << x << ", " << y << ") r=" << r << std::endl;}
};
✅ 抽象图形类(Abstraction)
class Shape {
protected:IRenderEngine* engine_; // 桥接成员
public:Shape(IRenderEngine* engine) : engine_(engine) {}virtual void draw() = 0;virtual ~Shape() = default;
};
✅ RefinedAbstraction(Circle)
class Circle : public Shape {float x_, y_, r_;
public:Circle(IRenderEngine* engine, float x, float y, float r): Shape(engine), x_(x), y_(y), r_(r) {}void draw() override {engine_->renderCircle(x_, y_, r_);}
};
✅ 使用示例
int main() {OpenGLRenderer opengl;VulkanRenderer vulkan;Circle circle1(&opengl, 10, 10, 5);Circle circle2(&vulkan, 20, 20, 10);circle1.draw();circle2.draw();return 0;
}
输出:
OpenGL 渲染圆: (10, 10) r=5
Vulkan 渲染圆: (20, 20) r=10
五、桥接适合的场景总结
应用场景 | 抽象维度 vs 实现维度 |
---|---|
图形渲染框架 | 图形类型(圆/矩形) × 渲染方式(OpenGL/Vulkan/Skia) |
消息推送系统 | 消息类型(普通/加密) × 推送方式(短信/邮件/钉钉) |
音视频播放引擎 | 媒体类型(音频/视频) × 编解码实现(FFmpeg/GStreamer) |
报表生成器 | 报表类型 × 导出格式(PDF/Excel/CSV) |
六、与其他模式的对比
模式 | 意图 | 适合场景说明 |
---|---|---|
桥接 Bridge | 抽象与实现分离,双维度可扩展 | 多维度变化,组合而非继承 |
适配器 | 接口兼容 | 老系统接入新接口 |
装饰器 | 功能增强 | 给原对象添加功能(可叠加) |
策略 | 算法切换 | 同一流程下支持不同行为切换 |
七、面试回答模板
“我们在图形模块中使用桥接模式,将图形类型与渲染方式解耦,图形如 Circle、Rectangle 不直接依赖 OpenGL 或 Vulkan,而是通过 IRenderEngine 接口进行桥接。这样我们新增图形类型或渲染引擎时,只需扩展对应层即可,符合开闭原则。”
✅ 建议强调:双维度扩展、组合替代继承、设计层次清晰
八、口诀记忆
“变化不交叉,维度可独立;抽象用桥接,组合不继承。”
九、明日预告:Day 14
组合模式(Composite Pattern):统一叶子节点与整体结构,构建树形层级的一致操作模型。