C++实现设计模式---桥接模式 (Bridge)
桥接模式 (Bridge)
桥接模式 是一种结构型设计模式,它通过将抽象部分与实现部分分离,使它们可以独立变化。桥接模式的核心思想是使用组合(而非继承)来扩展功能。
意图
- 将抽象部分与实现部分分离,使它们都可以独立地变化。
- 解决继承层次过深的问题,避免类的爆炸式增长。
使用场景
-
系统需要在抽象和实现之间解耦:
- 抽象和实现之间需要独立变化,使用继承会导致代码的复杂性上升。
-
避免类的数量爆炸:
- 系统中有多维度变化的对象(如颜色、形状、材质等),通过桥接模式可以避免每种组合都创建一个子类。
-
需要在运行时切换实现:
- 可以动态地改变抽象部分的实现,而不影响抽象部分。
参与者角色
-
抽象类 (Abstraction)
- 定义高层的抽象接口,持有对实现部分的引用。
-
扩展抽象类 (RefinedAbstraction)
- 在抽象类的基础上扩展,定义更具体的行为。
-
实现接口 (Implementor)
- 定义实现部分的接口,不同的实现类实现该接口。
-
具体实现类 (ConcreteImplementor)
- 实现具体的实现逻辑。
示例代码
以下代码展示了桥接模式的实现,用于抽象绘制不同颜色的形状。
#include <iostream>
#include <string>
// 实现接口:颜色
class Color {
public:
virtual ~Color() = default;
virtual std::string getColor() const = 0; // 获取颜色名称
};
// 具体实现类:红色
class Red : public Color {
public:
std::string getColor() const override {
return "红色";
}
};
// 具体实现类:蓝色
class Blue : public Color {
public:
std::string getColor() const override {
return "蓝色";
}
};
// 抽象类:形状
class Shape {
protected:
Color* color; // 通过组合方式持有颜色实现
public:
Shape(Color* c) : color(c) {}
virtual ~Shape() = default;
virtual void draw() const = 0; // 绘制形状的接口
};
// 扩展抽象类:圆形
class Circle : public Shape {
private:
double radius;
public:
Circle(Color* c, double r) : Shape(c), radius(r) {}
void draw() const override {
std::cout << "绘制一个半径为 " << radius << " 的 " << color->getColor() << " 圆形。" << std::endl;
}
};
// 扩展抽象类:矩形
class Rectangle : public Shape {
private:
double width;
double height;
public:
Rectangle(Color* c, double w, double h) : Shape(c), width(w), height(h) {}
void draw() const override {
std::cout << "绘制一个宽为 " << width << ",高为 " << height << " 的 " << color->getColor() << " 矩形。" << std::endl;
}
};
// 客户端代码
int main() {
// 创建具体颜色对象
Color* red = new Red();
Color* blue = new Blue();
// 创建形状对象并组合颜色
Shape* redCircle = new Circle(red, 5.0);
Shape* blueRectangle = new Rectangle(blue, 4.0, 6.0);
// 绘制形状
redCircle->draw();
blueRectangle->draw();
// 释放资源
delete redCircle;
delete blueRectangle;
delete red;
delete blue;
return 0;
}
代码解析
1. 实现接口 (Color)
Color
是实现部分的接口,定义了一个获取颜色的纯虚方法:
class Color {
public:
virtual ~Color() = default;
virtual std::string getColor() const = 0; // 获取颜色名称
};
Red
和Blue
是具体实现类,实现了Color
接口:
class Red : public Color {
public:
std::string getColor() const override {
return "红色";
}
};
2. 抽象类 (Shape)
Shape
是抽象类,持有Color
的引用:
class Shape {
protected:
Color* color; // 通过组合方式持有颜色实现
public:
Shape(Color* c) : color(c) {}
virtual ~Shape() = default;
virtual void draw() const = 0; // 绘制形状的接口
};
Circle
和Rectangle
是扩展抽象类,实现了draw
方法,具体描述如何绘制形状:
class Circle : public Shape {
private:
double radius;
public:
Circle(Color* c, double r) : Shape(c), radius(r) {}
void draw() const override {
std::cout << "绘制一个半径为 " << radius << " 的 " << color->getColor() << " 圆形。" << std::endl;
}
};
3. 客户端代码
- 客户端通过组合不同的颜色和形状,动态地创建对象,减少了继承的复杂性:
Color* red = new Red();
Shape* redCircle = new Circle(red, 5.0);
redCircle->draw(); // 绘制一个半径为 5 的红色圆形
优缺点
优点
- 分离抽象与实现:
- 抽象和实现可以独立扩展,互不影响。
- 提高灵活性:
- 通过组合的方式,可以在运行时动态更换实现部分。
- 避免继承层次复杂化:
- 解决了多维度变化导致的类爆炸问题。
缺点
- 增加系统复杂度:
- 引入了更多的类和接口,可能增加系统的理解难度。
- 运行成本:
- 由于使用了组合关系,可能会引入额外的间接层。
适用场景
-
需要跨维度扩展对象功能:
- 如形状与颜色、材质等维度的组合。
-
抽象与实现需要独立变化:
- 如需要在运行时动态替换实现类。
-
避免继承复杂性:
- 当系统中存在多个变化维度时,桥接模式可以有效减少子类的数量。
总结
桥接模式通过将抽象部分和实现部分分离,使得它们都可以独立扩展,解决了多维度扩展带来的复杂性问题。它是一种非常灵活的设计模式,适用于需要跨维度组合功能的场景。