桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。
概念解析
桥接模式的核心思想是:
-
解耦抽象与实现:将抽象部分和实现部分分离,使它们可以独立变化
-
组合优于继承:通过组合而不是继承来连接抽象和实现
-
多维度变化:适用于多个独立变化的维度
主要组成部分
-
抽象(Abstraction):定义抽象接口,维护一个指向实现者的引用
-
扩展抽象(Refined Abstraction):扩展抽象定义的接口
-
实现者(Implementor):定义实现类的接口
-
具体实现者(Concrete Implementor):实现实现者接口的具体类
代码示例
下面是一个完整的桥接模式示例,包含详细注释:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
// 实现者接口:绘图API
class DrawingAPI {
public:
virtual void drawCircle(double x, double y, double radius) = 0;
virtual void drawRectangle(double x1, double y1, double x2, double y2) = 0;
virtual ~DrawingAPI() = default;
};
// 具体实现者1:OpenGL绘图API
class OpenGLAPI : public DrawingAPI {
public:
void drawCircle(double x, double y, double radius) override {
std::cout << "OpenGL绘制圆形: 中心(" << x << "," << y << "), 半径" << radius << std::endl;
}
void drawRectangle(double x1, double y1, double x2, double y2) override {
std::cout << "OpenGL绘制矩形: 左上(" << x1 << "," << y1
<< "), 右下(" << x2 << "," << y2 << ")" << std::endl;
}
};
// 具体实现者2:Direct2D绘图API
class Direct2DAPI : public DrawingAPI {
public:
void drawCircle(double x, double y, double radius) override {
std::cout << "Direct2D绘制圆形: 中心(" << x << "," << y << "), 半径" << radius << std::endl;
}
void drawRectangle(double x1, double y1, double x2, double y2) override {
std::cout << "Direct2D绘制矩形: 左上(" << x1 << "," << y1
<< "), 右下(" << x2 << "," << y2 << ")" << std::endl;
}
};
// 抽象:形状
class Shape {
protected:
std::unique_ptr<DrawingAPI> drawingAPI_;
public:
explicit Shape(std::unique_ptr<DrawingAPI> api)
: drawingAPI_(std::move(api)) {}
virtual void draw() = 0; // 绘制形状
virtual void resize(double percentage) = 0; // 调整大小
virtual ~Shape() = default;
};
// 扩展抽象1:圆形
class Circle : public Shape {
private:
double x_, y_, radius_;
public:
Circle(double x, double y, double radius, std::unique_ptr<DrawingAPI> api)
: Shape(std::move(api)), x_(x), y_(y), radius_(radius) {}
void draw() override {
drawingAPI_->drawCircle(x_, y_, radius_);
}
void resize(double percentage) override {
radius_ *= (1.0 + percentage / 100.0);
std::cout << "圆形大小调整为: " << percentage << "%" << std::endl;
}
void move(double newX, double newY) {
x_ = newX;
y_ = newY;
std::cout << "圆形移动到: (" << newX << "," << newY << ")" << std::endl;
}
};
// 扩展抽象2:矩形
class Rectangle : public Shape {
private:
double x1_, y1_, x2_, y2_;
public:
Rectangle(double x1, double y1, double x2, double y2, std::unique_ptr<DrawingAPI> api)
: Shape(std::move(api)), x1_(x1), y1_(y1), x2_(x2), y2_(y2) {}
void draw() override {
drawingAPI_->drawRectangle(x1_, y1_, x2_, y2_);
}
void resize(double percentage) override {
double width = x2_ - x1_;
double height = y2_ - y1_;
width *= (1.0 + percentage / 100.0);
height *= (1.0 + percentage / 100.0);
x2_ = x1_ + width;
y2_ = y1_ + height;
std::cout << "矩形大小调整为: " << percentage << "%" << std::endl;
}
};
// 客户端代码
int main() {
std::cout << "=== 桥接模式演示 ===" << std::endl;
// 创建不同绘图API的实现
auto opengl = std::make_unique<OpenGLAPI>();
auto direct2d = std::make_unique<Direct2DAPI>();
// 创建使用不同API的形状
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Circle>(10, 10, 5, std::make_unique<OpenGLAPI>()));
shapes.push_back(std::make_unique<Rectangle>(5, 5, 15, 15, std::make_unique<Direct2DAPI>()));
shapes.push_back(std::make_unique<Circle>(20, 20, 8, std::make_unique<Direct2DAPI>()));
shapes.push_back(std::make_unique<Rectangle>(10, 10, 20, 20, std::make_unique<OpenGLAPI>()));
// 绘制并调整所有形状
for (auto& shape : shapes) {
shape->draw();
shape->resize(50); // 放大50%
shape->draw();
std::cout << std::endl;
}
// 动态改变绘图API
std::cout << "\n动态改变绘图API:" << std::endl;
auto circle = std::make_unique<Circle>(30, 30, 10, std::make_unique<OpenGLAPI>()));
circle->draw();
// 切换到Direct2D
circle = std::make_unique<Circle>(30, 30, 10, std::make_unique<Direct2DAPI>());
circle->draw();
return 0;
}
模式优势
-
分离抽象与实现:抽象和实现可以独立扩展,互不影响
-
提高可扩展性:可以独立地对抽象和实现进行扩展
-
减少子类数量:避免多层继承导致的类爆炸问题
-
开闭原则:符合开闭原则,可以扩展新的抽象和实现而不修改现有代码
-
隐藏实现细节:客户端只与抽象接口交互,不依赖具体实现
适用场景
-
当需要避免抽象和实现之间的永久绑定时
-
当抽象和实现都应该通过子类化进行扩展时
-
当对抽象的实现进行修改不应影响客户端代码时
-
当需要在运行时切换不同的实现时
-
当类存在多个独立变化的维度,且每个维度都需要进行扩展时