设计模式-桥接模式

一、桥接模式核心原理(通用)

桥接模式(Bridge Pattern)是结构型设计模式 ,核心思想是:将抽象部分与实现部分解耦,使两者可以独立变化

它解决的核心问题是:当一个类存在两个或多个独立变化的维度(比如「设备类型」和「品牌」、「图形形状」和「颜色」)时,多层继承会导致类数量呈指数级增长(类爆炸),而桥接模式通过「组合代替继承」,将两个维度拆分为独立的层级,通过「桥」(对象引用)连接,让每个维度可以独立扩展。

核心角色(C++ 实现中对应概念)
角色名称 作用 C++ 实现形式
实现化(Implementor) 定义实现层的通用接口,提供基础操作 纯虚类(接口类)
具体实现化(ConcreteImplementor) 实现 Implementor 接口,提供具体的基础操作 普通类(继承 Implementor)
抽象化(Abstraction) 定义抽象层接口,持有 Implementor 对象的引用(桥接核心),定义高层逻辑 抽象类(含 Implementor 指针)
扩展抽象化(RefinedAbstraction) 继承 Abstraction,细化抽象层接口,实现具体业务逻辑 普通类(继承 Abstraction)

二、C++ 代码示例(图形绘制:形状 + 颜色)

以「图形形状(抽象维度)」和「颜色(实现维度)」为例:

  • 抽象维度:圆形、矩形(可扩展新形状);
  • 实现维度:红色、蓝色(可扩展新颜色)。

这个场景中,形状和颜色是两个独立变化的维度,用桥接模式可以避免创建「红色圆形、蓝色圆形、红色矩形、蓝色矩形」等冗余类。

步骤 1:定义实现化接口(颜色接口)
cpp 复制代码
#include <iostream>
#include <string>

// 实现化(Implementor):颜色接口(纯虚类)
class Color {
public:
    // 纯虚函数:获取颜色名称
    virtual std::string getColorName() const = 0;
    // 虚析构函数:确保子类析构正常
    virtual ~Color() = default;
};
步骤 2:实现具体实现化类(具体颜色)
cpp 复制代码
// 具体实现化1:红色
class Red : public Color {
public:
    std::string getColorName() const override {
        return "红色";
    }
};

// 具体实现化2:蓝色
class Blue : public Color {
public:
    std::string getColorName() const override {
        return "蓝色";
    }
};
步骤 3:定义抽象化类(图形抽象类)

核心是持有「颜色」对象的指针(桥接的关键),定义图形的通用接口:

cpp 复制代码
// 抽象化(Abstraction):图形抽象类
class Shape {
protected:
    Color* color; // 持有实现化对象的指针(桥接核心:连接形状和颜色)
public:
    // 构造函数:注入颜色对象
    explicit Shape(Color* color) : color(color) {
        if (color == nullptr) {
            throw std::invalid_argument("Color pointer cannot be null!");
        }
    }

    // 纯虚函数:绘制图形(由子类实现)
    virtual void draw() const = 0;

    // 虚析构函数:释放颜色对象
    virtual ~Shape() {
        delete color;
        color = nullptr;
    }

    // 禁用拷贝构造和赋值(避免浅拷贝导致重复释放)
    Shape(const Shape&) = delete;
    Shape& operator=(const Shape&) = delete;

    // 移动构造和赋值(可选,提升性能)
    Shape(Shape&& other) noexcept : color(other.color) {
        other.color = nullptr;
    }
    Shape& operator=(Shape&& other) noexcept {
        if (this != &other) {
            delete color;
            color = other.color;
            other.color = nullptr;
        }
        return *this;
    }
};
步骤 4:实现扩展抽象化类(具体图形)
cpp 复制代码
// 扩展抽象化1:圆形
class Circle : public Shape {
private:
    double radius; // 圆形半径
public:
    // 构造函数:注入颜色+初始化半径
    Circle(Color* color, double radius) : Shape(color), radius(radius) {
        if (radius <= 0) {
            throw std::invalid_argument("Radius must be positive!");
        }
    }

    // 实现绘制逻辑
    void draw() const override {
        std::cout << "绘制一个" << color->getColorName() 
                  << "的圆形,半径:" << radius << std::endl;
    }
};

// 扩展抽象化2:矩形
class Rectangle : public Shape {
private:
    double width;  // 矩形宽度
    double height; // 矩形高度
public:
    // 构造函数:注入颜色+初始化宽高
    Rectangle(Color* color, double width, double height) 
        : Shape(color), width(width), height(height) {
        if (width <= 0 || height <= 0) {
            throw std::invalid_argument("Width and height must be positive!");
        }
    }

    // 实现绘制逻辑
    void draw() const override {
        std::cout << "绘制一个" << color->getColorName() 
                  << "的矩形,宽:" << width << ",高:" << height << std::endl;
    }
};
步骤 5:测试代码(主函数)
cpp 复制代码
int main() {
    try {
        // 场景1:红色圆形(半径5)
        Shape* redCircle = new Circle(new Red(), 5.0);
        redCircle->draw();

        // 场景2:蓝色矩形(宽10,高8)
        Shape* blueRect = new Rectangle(new Blue(), 10.0, 8.0);
        blueRect->draw();

        // 扩展演示:新增绿色(只需加Green类)、三角形(只需加Triangle类)
        // Shape* greenTriangle = new Triangle(new Green(), 6.0);
        // greenTriangle->draw();

        // 释放资源
        delete redCircle;
        delete blueRect;
        // delete greenTriangle;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
输出结果
cpp 复制代码
绘制一个红色的圆形,半径:5
绘制一个蓝色的矩形,宽:10,高:8
代码关键解释
  1. 桥接核心Shape 类中持有 Color* 指针,这是「桥」------ 形状(抽象维度)通过该指针调用颜色(实现维度)的方法,两者解耦;
  2. 资源管理 :C++ 中需手动管理内存,因此在 Shape 的析构函数中释放 color 指针,同时禁用拷贝构造 / 赋值(避免浅拷贝导致重复释放),可选实现移动语义;
  3. 异常处理:对空指针、非法参数(如负半径)做校验,符合 C++ 健壮性要求;
  4. 扩展能力 :新增「绿色」只需继承 Color,新增「三角形」只需继承 Shape,原有代码无需修改,符合「开闭原则」。

总结

  1. 桥接模式的核心是用组合(对象引用 / 指针)代替继承,分离「抽象维度」和「实现维度」,解决多层继承的类爆炸问题;
  2. C++ 实现中,「实现化」通常定义为纯虚类,「抽象化」持有其指针,通过构造函数注入具体实现对象,同时需注意内存管理(析构、禁用浅拷贝);
  3. 适用场景:当类有两个及以上独立变化的维度(如形状 + 颜色、品牌 + 功能),且需要灵活扩展时优先使用桥接模式。
相关推荐
im_AMBER几秒前
Leetcode 97 移除链表元素
c++·笔记·学习·算法·leetcode·链表
MindCareers5 分钟前
Beta Sprint Day 5-6: Android Development Improvement + UI Fixes
android·c++·git·sql·ui·visual studio·sprint
行稳方能走远14 分钟前
Android C++ 学习笔记2
c++
星火开发设计14 分钟前
链表详解及C++实现
数据结构·c++·学习·链表·指针·知识
修炼地15 分钟前
代码随想录算法训练营第五十三天 | 卡码网97. 小明逛公园(Floyd 算法)、卡码网127. 骑士的攻击(A * 算法)、最短路算法总结、图论总结
c++·算法·图论
QQ_43766431416 分钟前
Qt-框架
c++·qt
※※冰馨※※26 分钟前
【QT】初始化显示时正常,操作刷新后布局显示问题。
开发语言·c++·windows·qt
a35354138227 分钟前
设计模式-适配器模式
设计模式·适配器模式
溟洵28 分钟前
【C++ Qt 】中的多线程QThread已经线程安全相关的锁QMutex、QMutexLocker
c++·后端·qt
Lhan.zzZ30 分钟前
嵌入式Qt接收串口数据错乱问题分析:缓冲区残留数据的陷阱
开发语言·c++·qt