简单介绍
桥接模式属于 结构型模式 | 可将一个大类或一系列紧密相关的类拆分 为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
聚合关系:两个类处于不同的层次,强调了一个整体/局部的关系,当汽车对象销毁时,轮胎对象也可以单独存在
public class 轮胎{ }
public class 汽车{
protected:轮胎 tyre[4];
}
基础理解
Q:为什么要用桥接模式
A:使得抽象部分和实现部分分离,使它们可以独立地变化。且允许抽象部分和实现部分之间建立多对多的关系形成 聚合关系
Q:什么是抽象什么是实现
A:抽象 是一些实体的高阶控制层。抽象调用实现,实现来完成具体实现的工作
这里的形状就是抽象,与涂颜色(实现)形成聚合关系:抽象包含涂颜色
UML 图
解释:客户端只需要调用抽象部分。抽象部分与实现部分成为聚合关系。你可以详写一个精确的抽象,然后就可以在客户端用这个精确的抽象调用具体的实现。
空心箭头:继承关系
实线箭头:关联关系
棱形实线箭头:聚合关系
抽象部分和实现部分
在实际的程序中, 你可以在两个独立方向上扩展这种应用:
开发多个不同的 精确抽象 (例如:面向微信用户和支付宝用户 )
支持多个不同的 具体实现 (例如:能够使用 密码支付 人脸支付 和 指纹支付)。
- 抽象对象控制程序的外观
(微信用户和支付宝用户抽象成用户,通过这些抽象对象,我们可以统一对支付进行管理和调用,而不需要关心具体的支付实现方式。) - 并将真实工作委派给连入的实现对象
(抽象类与实现类发生聚合关系,抽象类可以调用密码支付 人脸支付 和 指纹支付方式) - 不同的实现只要遵循相同的接口就可以互换
(只要遵循了相同的接口:PaymentMode 支付接口,就可以在程序中互换使用) - 精确抽象(微信用户)就可以使用多个具体实现接口( 密码支付 人脸支付 和 指纹支付)
关键点:聚合关系,精确抽象类构造函数中对不同API 的调用
#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;
}
应用场景
如果你想要拆分或重组一个具有多重功能的庞杂类 (例如能与多个数据库服务器进行交互的类), 可以使用桥接模式。
桥接模式可以将庞杂类拆分为几个类层次结构。 此后, 你可以修改任意一个类层次结构而不会影响到其他类层次结构。 这种方法可以简化代码的维护工作, 并将修改已有代码的风险降到最低。
如果你需要在运行时切换不同实现方法, 可使用桥接模式。
当然并不是说一定要实现这一点, 桥接模式可替换抽象部分中的实现对象,只需要在抽象部分中引入实现对象,并通过接口进行交互。
顺便提一句, 最后一点是很多人混淆桥接模式和策略模式的主要原因。 记住, 设计模式并不仅是一种对类进行组织的方式, 它还能用于沟通意图和解决问题。
(在实现上有点像但是策略模式主要是针对算法,根据你的具体情况使用合适的策略算法)
与其他模式的关系
- 桥接、 状态模式和策略模式 (在某种程度上包括适配器) 模式的接口非常相似。 实际上, 它们都基于聚合模式——即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
- 你可以结合使用生成器模式和桥接模式: 主管类(定义调用构造步骤的顺序)负责抽象工作, 各种不同的生成器(会生成具体的产品)负责实现工作。
- 桥接模式通常会于开发前期进行设计, 使你能够将程序的各个部分独立开来以便开发。 另一方面, 适配器(为各种接口进行兼容和匹配)模式通常在已有程序中使用, 让相互不兼容的类能很好地合作。
浅薄理解,如果有错还望指正。谢谢大家。