桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。这种模式通过引入一个桥梁接口,将抽象层和实现层解耦,从而允许两者独立扩展。
桥接模式的核心角色
- Abstraction(抽象类):定义抽象接口,包含一个对实现类接口的引用
- RefinedAbstraction(扩展抽象类):扩展抽象类的接口
- Implementor(实现类接口):定义实现类的接口,供抽象类调用
- ConcreteImplementor(具体实现类):实现实现类接口的具体方法
C++实现示例
以下以"图形渲染"为例实现桥接模式,将图形的形状(抽象部分)与渲染方式(实现部分)分离,使它们可以独立变化:
cpp
#include <iostream>
#include <string>
// 实现类接口:渲染器(桥接的实现部分)
class Renderer {
public:
virtual ~Renderer() = default;
virtual void renderCircle(float radius) = 0;
virtual void renderSquare(float side) = 0;
};
// 具体实现类1:软件渲染
class SoftwareRenderer : public Renderer {
public:
void renderCircle(float radius) override {
std::cout << "软件渲染圆形,半径: " << radius << std::endl;
}
void renderSquare(float side) override {
std::cout << "软件渲染正方形,边长: " << side << std::endl;
}
};
// 具体实现类2:硬件渲染
class HardwareRenderer : public Renderer {
public:
void renderCircle(float radius) override {
std::cout << "硬件加速渲染圆形,半径: " << radius << std::endl;
}
void renderSquare(float side) override {
std::cout << "硬件加速渲染正方形,边长: " << side << std::endl;
}
};
// 抽象类:形状(桥接的抽象部分)
class Shape {
protected:
Renderer* renderer; // 持有实现部分的引用(桥接)
// 保护构造函数,只能被子类调用
Shape(Renderer* rend) : renderer(rend) {}
public:
virtual ~Shape() = default;
virtual void draw() = 0; // 绘制形状
virtual void resize(float factor) = 0; // 调整大小
};
// 扩展抽象类1:圆形
class Circle : public Shape {
private:
float radius;
public:
Circle(Renderer* rend, float r) : Shape(rend), radius(r) {}
void draw() override {
renderer->renderCircle(radius); // 调用实现部分
}
void resize(float factor) override {
radius *= factor;
}
};
// 扩展抽象类2:正方形
class Square : public Shape {
private:
float side;
public:
Square(Renderer* rend, float s) : Shape(rend), side(s) {}
void draw() override {
renderer->renderSquare(side); // 调用实现部分
}
void resize(float factor) override {
side *= factor;
}
};
// 客户端代码
int main() {
// 创建不同的渲染器(实现部分)
Renderer* software = new SoftwareRenderer();
Renderer* hardware = new HardwareRenderer();
// 创建不同的形状(抽象部分),并与渲染器桥接
Shape* circle = new Circle(software, 5.0f);
Shape* square = new Square(hardware, 10.0f);
// 绘制形状
std::cout << "第一次绘制:" << std::endl;
circle->draw();
square->draw();
// 调整大小后再次绘制
std::cout << "\n调整大小后绘制:" << std::endl;
circle->resize(2.0f);
square->resize(0.5f);
circle->draw();
square->draw();
// 更换圆形的渲染器(动态改变实现)
std::cout << "\n更换渲染器后绘制圆形:" << std::endl;
delete circle;
circle = new Circle(hardware, 5.0f);
circle->draw();
// 清理资源
delete circle;
delete square;
delete software;
delete hardware;
return 0;
}
代码解析
-
Renderer类:实现类接口,定义了渲染圆形和正方形的接口方法,是桥接模式中的"实现部分"。
-
SoftwareRenderer和HardwareRenderer:具体实现类,分别提供了软件渲染和硬件加速渲染的具体实现。
-
Shape类:抽象类,定义了形状的基本接口(绘制和调整大小),并持有一个Renderer指针作为桥梁,连接抽象部分和实现部分。
-
Circle和Square:扩展抽象类,继承自Shape并实现了具体形状的绘制和调整大小方法,通过调用Renderer的方法完成实际渲染。
-
桥接关系:形状(抽象部分)不直接实现渲染功能,而是通过Renderer(实现部分)完成,使形状和渲染方式可以独立变化。
桥接模式的优缺点
优点:
- 分离抽象与实现,使两者可以独立扩展,符合开放-封闭原则
- 减少子类数量,避免了抽象与实现的组合爆炸(如2种形状×2种渲染=4种组合,而非传统继承的4个子类)
- 可以动态切换实现方式,提高系统灵活性
- 隐藏实现细节,抽象层只需关注自身接口
缺点:
- 增加了系统的复杂度,理解和设计难度较大
- 需要正确识别系统中的抽象层和实现层,否则可能滥用模式
适用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要扩展时
- 当需要避免抽象部分与实现部分的紧耦合时
- 当希望动态切换实现方式时
- 当系统中存在多个层次的继承关系,导致类数量急剧增加时
常见应用:
- 图形界面中的窗口系统(窗口样式与绘制系统分离)
- 跨平台应用开发(业务逻辑与平台相关实现分离)
- 数据库驱动(数据访问抽象与具体数据库实现分离)
- 消息系统(消息格式与传输协议分离)
桥接模式与适配器模式的区别:桥接模式是在设计初期就将抽象与实现分离,而适配器模式是在已有接口不兼容时进行适配。