C++ 【桥接模式】

简单介绍

桥接模式 属于 结构型模式 | 可将一个大类或一系列紧密相关的类拆分 为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。

聚合关系:两个类处于不同的层次,强调了一个整体/局部的关系,当汽车对象销毁时,轮胎对象也可以单独存在

cpp 复制代码
public class 轮胎{  }
public class 汽车{
    protected:轮胎 tyre[4];
}

基础理解

Q:为什么要用桥接模式

A:使得抽象部分和实现部分分离,使它们可以独立地变化。且允许抽象部分和实现部分之间建立多对多的关系形成 聚合关系

Q:什么是抽象什么是实现

A:抽象 是一些实体的高阶控制层。抽象调用实现,实现来完成具体实现的工作

这里的形状就是抽象,与涂颜色(实现)形成聚合关系:抽象包含涂颜色

UML 图

解释:客户端只需要调用抽象部分。抽象部分与实现部分成为聚合关系。你可以详写一个精确的抽象,然后就可以在客户端用这个精确的抽象调用具体的实现。


空心箭头:继承关系

实线箭头:关联关系

棱形实线箭头:聚合关系

抽象部分和实现部分

在实际的程序中, 你可以在两个独立方向上扩展这种应用:

开发多个不同的 精确抽象 (例如:面向微信用户和支付宝用户 )

支持多个不同的 具体实现 (例如:能够使用 密码支付 人脸支付 和 指纹支付)。

  1. 抽象对象控制程序的外观
    (微信用户和支付宝用户抽象成用户,通过这些抽象对象,我们可以统一对支付进行管理和调用,而不需要关心具体的支付实现方式。)
  2. 并将真实工作委派给连入的实现对象
    (抽象类与实现类发生聚合关系,抽象类可以调用密码支付 人脸支付 和 指纹支付方式)
  3. 不同的实现只要遵循相同的接口就可以互换
    (只要遵循了相同的接口:PaymentMode 支付接口,就可以在程序中互换使用)
  4. 精确抽象(微信用户)就可以使用多个具体实现接口( 密码支付 人脸支付 和 指纹支付)

关键点:聚合关系,精确抽象类构造函数中对不同API 的调用

cpp 复制代码
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;

// 支付方式接口
class PaymentMode
{
public:
    virtual ~PaymentMode() {}
    virtual bool security(string uId) = 0;
};

// 具体支付方式实现类:密码支付
class PayByCypher : public PaymentMode
{
public:
    bool security(string uId) override
    {
        cout << "密码支付的安全检查" << endl;
        // 实现具体的安全验证逻辑
        return true;
}
}
;

// 具体支付方式实现类:人脸支付
class PayByFace : public PaymentMode
{
public:
    bool security(string uId) override
    {
        cout << "人脸支付的安全检查" << endl;
        // 实现具体的安全验证逻辑
        return true;
    }
};

// 具体支付方式实现类:指纹支付
class PayByFingerprint : public PaymentMode
{
public:
    bool security(string uId) override
    {
        cout << "指纹支付的安全检查" << endl;
        // 实现具体的安全验证逻辑
        return true;
    }
};

// 支付抽象类
class Payment
{
public:
    Payment(PaymentMode *mode_) : mode(mode_) {}
    virtual ~Payment() {}
    virtual void pay(string uId, string tradeId, long long amount) = 0;

protected:
    PaymentMode *mode;
};

// 扩展抽象化角色:微信支付
class WxPayment : public Payment
{
public:
    WxPayment(PaymentMode *mode) : Payment(mode) {}

    void pay(string uId, string tradeId, long long amount) override
    {
        cout << "使用微信支付" << endl;
        bool isSecure = mode->security(uId);
        if (isSecure)
        {
            cout << "微信支付成功,交易号:" << tradeId << ",金额:" << amount << endl;
        }
        else
        {
            cout << "微信支付失败,交易号:" << tradeId << ",金额:" << amount << endl;
        }
    }
};

// 扩展抽象化角色:支付宝支付
class AliPayment : public Payment
{
public:
    AliPayment(PaymentMode *mode) : Payment(mode) {}

    void pay(string uId, string tradeId, long long amount) override
    {
        cout << "支付宝支付开始" << endl;
        bool isSecure = mode->security(uId);
        if (isSecure)
        {
            cout << "支付宝支付成功,交易号:" << tradeId << ",金额:" << amount << endl;
        }
        else
        {
            cout << "支付宝支付失败,交易号:" << tradeId << ",金额:" << amount << endl;
        }
    }
};

int main()
{
    PaymentMode *cypherMode = new PayByCypher();
    PaymentMode *faceMode = new PayByFace();

    Payment *wxPayment = new WxPayment(cypherMode);
    Payment *aliPayment = new AliPayment(faceMode);

    wxPayment->pay("user123", "123456", 100);
    aliPayment->pay("user456", "789012", 200);

    delete cypherMode;
    delete faceMode;
    delete wxPayment;
    delete aliPayment;

    system("pause");
    return 0;
}

应用场景

如果你想要拆分或重组一个具有多重功能的庞杂类 (例如能与多个数据库服务器进行交互的类), 可以使用桥接模式。

桥接模式可以将庞杂类拆分为几个类层次结构。 此后, 你可以修改任意一个类层次结构而不会影响到其他类层次结构。 这种方法可以简化代码的维护工作, 并将修改已有代码的风险降到最低。

如果你需要在运行时切换不同实现方法, 可使用桥接模式。

当然并不是说一定要实现这一点, 桥接模式可替换抽象部分中的实现对象,只需要在抽象部分中引入实现对象,并通过接口进行交互。

顺便提一句, 最后一点是很多人混淆桥接模式和策略模式的主要原因。 记住, 设计模式并不仅是一种对类进行组织的方式, 它还能用于沟通意图和解决问题。

(在实现上有点像但是策略模式主要是针对算法,根据你的具体情况使用合适的策略算法)

与其他模式的关系

  1. 桥接、 状态模式和策略模式 (在某种程度上包括适配器) 模式的接口非常相似。 实际上, 它们都基于聚合模式------即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
  2. 你可以结合使用生成器模式和桥接模式: 主管类(定义调用构造步骤的顺序)负责抽象工作, 各种不同的生成器(会生成具体的产品)负责实现工作。
  3. 桥接模式通常会于开发前期进行设计, 使你能够将程序的各个部分独立开来以便开发。 另一方面, 适配器(为各种接口进行兼容和匹配)模式通常在已有程序中使用, 让相互不兼容的类能很好地合作。

浅薄理解,如果有错还望指正。谢谢大家。

相关推荐
ragnwang3 小时前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
lqqjuly6 小时前
特殊的“Undefined Reference xxx“编译错误
c语言·c++
冰红茶兑滴水7 小时前
云备份项目--工具类编写
linux·c++
刘好念7 小时前
[OpenGL]使用 Compute Shader 实现矩阵点乘
c++·计算机图形学·opengl·glsl
酒鬼猿7 小时前
C++进阶(二)--面向对象--继承
java·开发语言·c++
姚先生978 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode
小王爱吃月亮糖9 小时前
QT开发【常用控件1】-Layouts & Spacers
开发语言·前端·c++·qt·visual studio
aworkholic9 小时前
opencv sdk for java中提示无stiching模块接口的问题
java·c++·opencv·jni·opencv4android·stiching
程序员老冯头9 小时前
第十六章 C++ 字符串
开发语言·c++
Xenia2239 小时前
复习篇~第二章程序设计基础
c++·算法