注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。
抽象与实现的解耦之道
1. 模式定义与用途
核心思想
- 桥接模式:将抽象部分与实现部分分离,使二者可以独立变化。
- 关键用途:
1.拆分复杂继承树:避免因多维度扩展导致的类爆炸。
2.运行时切换实现:动态组合不同的抽象与实现(如渲染引擎、数据存储方式)。 - 经典场景
1.图形库:形状(抽象)与渲染API(实现)的组合。
2.设备控制:遥控器(抽象)与电器设备(实现)的解耦。
2. 模式结构解析
+---------------------+ +---------------------+
| Abstraction | | Implementor |
+---------------------+ +---------------------+
| - impl: Implementor |<>------->| + operationImpl() |
| + operation(): void | +---------------------+
+---------------------+ ^ ^ | | +-----+-------------+ | | |
+---------------------+ +-------------------+ +-------------------+
| RefinedAbstraction | | ConcreteImplA | | ConcreteImplB |
+---------------------+ +-------------------+ +-------------------+
| + operation() | | + operationImpl() | | + operationImpl() |
+---------------------+ +-------------------+ +-------------------+
角色说明
Abstraction
:抽象部分的基类,持有实现部分的引用。-
RefinedAbstraction
:扩展抽象功能的具体类。 Implementor
:实现部分的接口。ConcreteImplementor
:实现部分的具体类。
3. 简单示例:图形渲染引擎桥接
场景:形状与渲染API解耦
// 实现部分:渲染API接口
class RenderAPI {
public: virtual void renderCircle(float x, float y, float radius) = 0; virtual ~RenderAPI() = default;
}; // 抽象部分:形状基类
class Shape {
public: Shape(RenderAPI& api) : api_(api) {} virtual void draw() = 0;
protected: RenderAPI& api_;
}; // 客户端调用
class Circle : public Shape {
public: Circle(RenderAPI& api, float x, float y, float r) : Shape(api), x_(x), y_(y), radius_(r) {} void draw() override { api_.renderCircle(x_, y_, radius_); }
private: float x_, y_, radius_;
};
4. 完整代码:多API与多形状支持
步骤1:实现部分(渲染API)
// 实现接口
class RenderAPI {
public: virtual void renderCircle(float x, float y, float radius) = 0; virtual void renderRect(float x, float y, float w, float h) = 0; virtual ~RenderAPI() = default;
}; // OpenGL实现
class OpenGLAPI : public RenderAPI {
public: void renderCircle(float x, float y, float radius) override { std::cout << "OpenGL渲染圆形:位置(" << x << "," << y << "), 半径" << radius << "\n"; } void renderRect(float x, float y, float w, float h) override { std::cout << "OpenGL渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n"; }
}; // Vulkan实现
class VulkanAPI : public RenderAPI {
public: void renderCircle(float x, float y, float radius) override { std::cout << "Vulkan渲染圆形:位置(" << x << "," << y << "), 半径" << radius << "\n"; } void renderRect(float x, float y, float w, float h) override { std::cout << "Vulkan渲染矩形:位置(" << x << "," << y << "), 尺寸" << w << "x" << h << "\n"; }
};
步骤2:抽象部分(形状与扩展)
// 抽象基类(使用智能指针管理实现)
class Shape {
public: Shape(std::shared_ptr<RenderAPI> api) : api_(api) {} virtual void draw() = 0; virtual ~Shape() = default;
protected: std::shared_ptr<RenderAPI> api_;
}; // 具体形状:圆形
class Circle : public Shape {
public: Circle(std::shared_ptr<RenderAPI> api, float x, float y, float r) : Shape(api), x_(x), y_(y), radius_(r) {} void draw() override { api_->renderCircle(x_, y_, radius_); }
private: float x_, y_, radius_;
}; // 具体形状:矩形
class Rectangle : public Shape {
public: Rectangle(std::shared_ptr<RenderAPI> api, float x, float y, float w, float h) : Shape(api), x_(x), y_(y), width_(w), height_(h) {} void draw() override { api_->renderRect(x_, y_, width_, height_); }
private: float x_, y_, width_, height_;
};
步骤3:客户端动态组合
int main() { // 创建不同渲染API auto opengl = std::make_shared<OpenGLAPI>(); auto vulkan = std::make_shared<VulkanAPI>(); // 动态组合形状与API Circle glCircle(opengl, 10, 10, 5); Circle vkCircle(vulkan, 20, 20, 8); Rectangle glRect(opengl, 5, 5, 10, 6); glCircle.draw(); // 输出:OpenGL渲染圆形:位置(10,10), 半径5 vkCircle.draw(); // 输出:Vulkan渲染圆形:位置(20,20), 半径8 glRect.draw(); // 输出:OpenGL渲染矩形:位置(5,5), 尺寸10x6
}
5. 优缺点分析
优点 | 缺点 |
---|---|
分离抽象与实现,减少继承层次 | 增加类的数量 |
支持运行时动态切换实现 | 需要设计合理的抽象接口 |
提升跨平台、跨模块的扩展性 | 对简单场景可能过度设计 |
6. 调试与优化策略
调试技巧(VS2022)
- 验证桥接连接:
在draw()
方法中设置断点,检查api_指针是否指向正确的实现对象。 - 多态类型识别:
使用typeid(*api_).name()
输出实际类型(需启用RTTI)。
性能优化
- 缓存实现对象:
对频繁使用的实现(如OpenGLAPI)使用单例或对象池。 - 移动语义优化:
// 使用移动语义传递渲染API所有权
Shape(std::shared_ptr<RenderAPI>&& api) : api_(std::move(api)) {}