欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 【第六节】C++设计模式(结构型模式)-Bridge(桥接)模式

【第六节】C++设计模式(结构型模式)-Bridge(桥接)模式

2025/5/9 7:26:33 来源:https://blog.csdn.net/linshantang/article/details/145848676  浏览:    关键词:【第六节】C++设计模式(结构型模式)-Bridge(桥接)模式

目录

一、问题提出

二、桥接模式的结构与优势

三、桥接模式的实现

四、桥接模式的深入讨论

五、总结


一、问题提出

面向对象设计的核心原则
        面向对象设计的核心可以总结为两点:松耦合(Coupling)和高内聚(Cohesion)。面向对象系统的目标是通过提高模块内部的内聚性,降低模块间的耦合性来构建灵活、可维护的系统。然而,在实际开发中,这一目标往往难以实现,开发者常常面临以下典型问题:

(1)初始实现:客户提出需求,开发者使用一个类(A)来实现功能。
(2)算法扩展:需求变化,需要支持两种算法,于是设计调整为抽象基类,并派生出两个具体类(A1 和 A2)来实现不同的算法。
(3)平台扩展:客户要求支持不同操作系统,于是再抽象出一个基类(A0),并为每个操作系统派生具体类(A00 和 A01,其中 A00 是原来的类 A)。此时,系统中已有 4 个类。
(4)需求持续变化:客户又提出新的算法需求,类的数量进一步增加。
(5)类爆炸问题:随着需求的不断变化,类的数量迅速膨胀,系统变得难以维护。

        桥接模式正是为了解决这类问题而提出的。

二、桥接模式的结构与优势

模式结构
桥接模式的典型结构如下图所示。该模式将系统分为两个独立的部分:
        抽象部分:定义高层业务逻辑。
        实现部分:封装具体实现细节。

        这两个部分可以独立地进行修改和扩展。例如,当需求变化需要从抽象部分派生新的子类时,不再需要通过继承来添加子类(如上面举例的 A1 和 A2)。同样,当需要添加新的算法时,只需修改实现部分,而无需改动抽象部分。

模式优势
通过桥接模式,系统的扩展变得更加优雅:
        抽象与实现分离:抽象部分和实现部分可以独立变化,互不影响。
        减少类爆炸:通过组合而非继承,避免了类的数量呈指数级增长。
        提高可维护性:系统结构更加清晰,维护成本显著降低。

三、桥接模式的实现

以下是桥接模式的完整代码示例(使用 C++ 实现):

代码片段 1:Abstraction.h

// Abstraction.h
#ifndef _ABSTRACTION_H_      // 防止头文件被多次包含
#define _ABSTRACTION_H_// 前向声明 AbstractionImp 类,避免头文件依赖
class AbstractionImp;// 抽象类 Abstraction:定义高层接口
class Abstraction {
public:virtual ~Abstraction() = default;  // 虚析构函数,确保派生类对象能够正确释放资源virtual void Operation() = 0;       // 纯虚函数,定义抽象接口
protected:Abstraction() = default;            // 构造函数,保护权限,防止直接实例化
private:// 禁用拷贝构造函数和赋值运算符,防止对象复制Abstraction(const Abstraction&) = delete;Abstraction& operator=(const Abstraction&) = delete;
};// 具体抽象类 RefinedAbstraction:继承自 Abstraction,实现高层接口
class RefinedAbstraction : public Abstraction {
public:explicit RefinedAbstraction(AbstractionImp* imp);  // 显式构造函数,接受实现部分的指针~RefinedAbstraction() override;                   // 析构函数void Operation() override;                        // 实现抽象接口
private:AbstractionImp* _imp;  // 指向实现部分的指针,通过组合方式实现桥接
};#endif //~_ABSTRACTION_H_


 

代码片段 2:Abstraction.cpp

// Abstraction.cpp
#include "Abstraction.h"
#include "AbstractionImp.h"
#include <iostream>
using namespace std;// Abstraction 构造函数和析构函数
Abstraction::Abstraction() = default;
Abstraction::~Abstraction() = default;// RefinedAbstraction 构造函数
RefinedAbstraction::RefinedAbstraction(AbstractionImp* imp) : _imp(imp) {}// RefinedAbstraction 析构函数
RefinedAbstraction::~RefinedAbstraction() {delete _imp;  // 释放实现部分的对象
}// RefinedAbstraction 的 Operation 实现
void RefinedAbstraction::Operation() {_imp->Operation();  // 委托给实现部分执行具体操作
}

代码片段 3:AbstractionImp.h

// AbstractionImp.h
#ifndef _ABSTRACTIONIMP_H_      // 防止头文件被多次包含
#define _ABSTRACTIONIMP_H_// 实现类 AbstractionImp:定义具体实现的接口
class AbstractionImp {
public:virtual ~AbstractionImp() = default;  // 虚析构函数,确保派生类对象能够正确释放资源virtual void Operation() = 0;         // 纯虚函数,定义具体实现接口
protected:AbstractionImp() = default;           // 构造函数,保护权限,防止直接实例化
private:// 禁用拷贝构造函数和赋值运算符,防止对象复制AbstractionImp(const AbstractionImp&) = delete;AbstractionImp& operator=(const AbstractionImp&) = delete;
};// 具体实现类 ConcreteAbstractionImpA
class ConcreteAbstractionImpA : public AbstractionImp {
public:ConcreteAbstractionImpA() = default;  // 构造函数~ConcreteAbstractionImpA() override = default;  // 析构函数void Operation() override;  // 实现具体操作
};// 具体实现类 ConcreteAbstractionImpB
class ConcreteAbstractionImpB : public AbstractionImp {
public:ConcreteAbstractionImpB() = default;  // 构造函数~ConcreteAbstractionImpB() override = default;  // 析构函数void Operation() override;  // 实现具体操作
};#endif //~_ABSTRACTIONIMP_H_

代码片段 4:AbstractionImp.cpp

// AbstractionImp.cpp
#include "AbstractionImp.h"
#include <iostream>
using namespace std;// AbstractionImp 构造函数和析构函数
AbstractionImp::AbstractionImp() = default;
AbstractionImp::~AbstractionImp() = default;// ConcreteAbstractionImpA 的 Operation 实现
void ConcreteAbstractionImpA::Operation() {cout << "ConcreteAbstractionImpA...." << endl;
}// ConcreteAbstractionImpB 的 Operation 实现
void ConcreteAbstractionImpB::Operation() {cout << "ConcreteAbstractionImpB...." << endl;
}

代码片段 5:main.cpp

// main.cpp
#include "Abstraction.h"
#include "AbstractionImp.h"
#include <iostream>
using namespace std;int main(int argc, char* argv[]) {// 创建具体实现对象AbstractionImp* imp = new ConcreteAbstractionImpA();// 创建具体抽象对象,并注入实现对象Abstraction* abs = new RefinedAbstraction(imp);// 执行操作abs->Operation();// 释放资源delete abs;  // abs 的析构函数会释放 impreturn 0;
}

代码说明
        桥接模式通过将抽象部分(Abstraction 类)和实现部分(AbstractionImp 类)分离,使得两者可以独立变化。这种设计方式显著降低了系统的耦合性。

四、桥接模式的深入讨论

模式理解难点
        桥接模式是设计模式中较为复杂且难以理解的一种,但其在面向对象开发中应用广泛。GoF 在描述桥接模式时指出,该模式“将抽象部分与它的实现部分分离,使得它们可以独立地变化”。这句话看似简单,却容易引发误解。

        Bruce Eckel 在《Thinking in Patterns》中提到,桥接模式是 GoF 描述得最不清晰的设计模式之一。主要原因在于“实现”一词的含义。通常情况下,“实现”指的是继承基类并实现其接口,但在桥接模式中,“实现”指的是通过组合(委托)的方式来实现用户需求。理解这一点是掌握桥接模式的关键。

组合优于继承
        桥接模式的核心思想是通过组合而非继承来实现功能需求。这正是面向对象设计中的一个重要原则:**优先使用组合而非继承(Favor Composition Over Inheritance)**。继承虽然强大,但容易导致类层次结构复杂化,而组合则提供了更大的灵活性和更低的耦合性。

五、总结

        桥接模式通过解耦抽象与实现,有效地解决了面向对象设计中的类爆炸问题。它不仅提高了系统的可维护性,还为系统的扩展提供了更大的灵活性。理解并掌握桥接模式,将使你的设计更加优雅和高效。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词