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

news/2025/2/26 20:14:06

目录

一、问题提出

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

三、桥接模式的实现

四、桥接模式的深入讨论

五、总结


一、问题提出

面向对象设计的核心原则
        面向对象设计的核心可以总结为两点:松耦合(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 的析构函数会释放 imp
    return 0;
}

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

四、桥接模式的深入讨论

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

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

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

五、总结

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


http://www.niftyadmin.cn/n/5869133.html

相关文章

SSL 证书是 SSL 协议实现安全通信的必要组成部分

SSL证书和SSL/TLS协议有着密切的关系&#xff0c;但它们本质上是不同的概念。下面是两者的区别和它们之间的关系的表格&#xff1a; 属性SSL/TLS 协议SSL证书英文全称SSL&#xff08;Secure Sockets Layer&#xff09;&#xff0c;TLS&#xff08;Transport Layer Security&am…

【音视频】音视频录制、播放原理

一、音视频录制原理 通常&#xff0c;音视频录制的步骤如下图所示&#xff1a; 我们分别从音频和视频开始采样&#xff0c;通过麦克风和摄像头来接受我们的音频信息和图像信息&#xff0c;这通常是同时进行的&#xff0c;不过&#xff0c;通常视频的采集会比音频的采集慢&…

网络原理---HTTP/HTTPS

通过之前的网络编程&#xff0c;我们已经初步了解UDP和TCP的基本实现方法&#xff0c;接下来我们对其进一步的学习。 在网络编程中&#xff1a; 1.读和写数据通过Socket&#xff0c;通过Socket内置的InputStream和OutputStream(读写的基本单位都是字节&#xff09;。2.当在编…

半导体芯片制造中 W CVD(钨化学气相沉积)

半导体芯片制造中 W CVD&#xff08;钨化学气相沉积&#xff09; 的 Nucleation 解析 在钨&#xff08;W&#xff09;化学气相沉积&#xff08;CVD&#xff09;工艺中&#xff0c;Nucleation&#xff08;成核&#xff09; 是沉积过程的初始阶段&#xff0c;指钨原子或分子在基…

Ollama辅助工具在思源笔记中的核心玩法助力实现AI高效创作

前言&#xff1a;在创作的道路上&#xff0c;找到合适的工具就像找到了一位贴心的好伙伴。思源笔记以其强大的编辑功能、灵活的整理方式和丰富的插件支持&#xff0c;成为了许多写作者的心头好。无论是记录闪现的灵感火花&#xff0c;还是撰写复杂的文档&#xff0c;它都能轻松…

基于STM32的智能工业生产线质量检测系统

1. 引言 传统工业质检依赖人工目检与抽样检测&#xff0c;存在效率低、漏检率高、标准不统一等问题。本文设计了一款基于STM32的智能工业生产线质量检测系统&#xff0c;通过机器视觉、多传感器融合与AI缺陷识别技术&#xff0c;实现产品全检自动化、缺陷分类精准化与质量追溯…

深入解析React useEffect与useLayoutEffect:区别、原理与实践

&#x1f30c; ‌深入解析React useEffect与useLayoutEffect&#xff1a;区别、原理与实践 在React函数组件中&#xff0c;useEffect和useLayoutEffect是处理副作用的两个核心Hook。它们看似相似&#xff0c;但在执行时机和应用场景上有本质区别。本文将通过‌原理剖析‌、‌对…

【虚拟仪器技术】labview操作指南和虚拟仪器技术习题答案(一)

今天是2025年2月24日&#xff0c;画的是fate/Grand Order里面的阿尔托莉雅.卡斯特&#xff0c;武内老师的画。 目录 第1章 第2章 第3章 第4章 第5章 关注作者了解更多 我的其他CSDN专栏 毕业设计 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程…