桥接模式(Bridge Pattern)在嵌入式支付系统中的应用
桥接模式是一种 **结构型设计模式**,它通过将抽象部分和实现部分分离,使得它们可以独立变化。桥接模式采用组合代替继承,避免了多层继承的复杂性,并为系统提供了更高的灵活性。抽象部分(Abstraction):定义了系统中的高层业务逻辑,并持有对实现部分的引用。实现部分(Implementor):定义了具体的功能实现接口,并由具体的实现类来完成。通过桥接模式,我们可以让每个维度(例如支付渠道和支付方
在嵌入式软件开发中,常常会遇到需要支持多个维度变化的场景。比如,在支付系统中,我们需要同时支持不同的 **支付渠道**(如微信支付、支付宝支付、银行卡支付等)和 **支付方式**(如密码支付、人脸支付、指纹支付等)。如果不加以合理设计,代码会变得非常复杂且不易扩展。为了应对这种需求,我们可以使用 桥接模式(Bridge Pattern) 来进行解耦,提升系统的扩展性和可维护性。
本文将以 售卖饮料机的嵌入式支付系统 为例,讲解 桥接模式 的定义、应用场合,以及如何通过桥接模式实现灵活的支付渠道与支付方式的组合。我们还将展示不使用桥接模式和使用桥接模式时代码的变化,帮助您更好地理解这种模式的优势。
1. 什么是桥接模式?
1.1 桥接模式定义
桥接模式是一种 **结构型设计模式**,它通过将 抽象部分 和 实现部分 分离,使得它们可以独立变化。桥接模式采用 组合 代替继承,避免了多层继承的复杂性,并为系统提供了更高的灵活性。
-
抽象部分(Abstraction):定义了系统中的高层业务逻辑,并持有对实现部分的引用。
-
实现部分(Implementor):定义了具体的功能实现接口,并由具体的实现类来完成。
通过桥接模式,我们可以让每个维度(例如支付渠道和支付方式)独立变化,从而避免代码复杂度的增加。
1.2 桥接模式的应用场合
桥接模式特别适用于以下场景:
-
多维度变化的需求:当类的变化维度超过一个时,例如在支付系统中,支付渠道和支付方式是两个独立的变化维度。
-
避免继承层次的膨胀:当多个变化维度通过继承实现时,会导致类的数量急剧增加,系统难以维护。
-
系统需要高度扩展性:希望系统能够在不修改现有代码的基础上,轻松扩展新的功能和维度。
2. 不使用桥接模式的实现
2.1 需求
假设我们在一个售卖饮料的嵌入式系统中,需要实现支付功能。支付功能支持 微信支付 和 **支付宝支付**,支付方式包括 **密码支付**、**人脸支付** 和 **指纹支付**。如果不使用桥接模式,代码将会变得非常复杂,尤其是当我们需要增加新的支付渠道(例如银行卡支付)时。
2.2 不使用设计模式实现
#include <stdio.h>
int doPay(int channelType, int modeType)
{
// 微信支付
if (channelType == 1)
{
printf("微信支付开始...\n");
if (modeType == 1)
{
printf("密码支付\n");
}
else if (modeType == 2)
{
printf("人脸支付\n");
}
else if (modeType == 3)
{
printf("指纹支付\n");
}
}
// 支付宝支付
else if (channelType == 2)
{
printf("支付宝支付开始...\n");
if (modeType == 1)
{
printf("密码支付\n");
}
else if (modeType == 2)
{
printf("人脸支付\n");
}
else if (modeType == 3)
{
printf("指纹支付\n");
}
}
return 0;
}
int main()
{
// 测试:微信支付,人脸支付
printf("测试:微信支付、人脸支付方式\n");
doPay(1, 2); // 微信支付 + 人脸支付
// 测试:支付宝支付,指纹支付
printf("\n测试:支付宝支付、指纹支付方式\n");
doPay(2, 3); // 支付宝支付 + 指纹支付
return 0;
}
2.3 代码问题
-
扩展性差:每新增一种支付方式或支付渠道,都需要修改
doPay
方法,违反了 **开闭原则**。 -
代码冗长:随着支付渠道和支付方式的增加,
if-else
语句会变得非常复杂,代码维护成本高。
2.4 新需求:添加银行卡支付
如果我们现在需要支持 **银行卡支付**,不使用桥接模式的实现会是这样的:
// 在原有基础上增加银行卡支付的判断
if (channelType == 3)
{
printf("银行卡支付开始...\n");
if (modeType == 1)
{
printf("密码支付\n");
}
else if (modeType == 2)
{
printf("人脸支付\n");
}
else if (modeType == 3)
{
printf("指纹支付\n");
}
}
随着需求的增加,代码会变得更加庞大且不易维护,修改代码的地方也会更多。
3. 使用桥接模式的实现
3.1 需求
我们希望通过桥接模式来实现支付系统的灵活扩展,支持多种支付渠道和支付方式。通过将支付渠道和支付方式分离,我们可以方便地添加新的支付方式或支付渠道,而不需要修改现有代码。
3.2 使用桥接模式的设计
-
支付模式接口(IPayMode):定义支付模式的接口。
-
支付抽象类(Pay):定义支付渠道,并持有支付模式接口的引用。
-
具体支付渠道(WxPay、ZfbPay、BankPay):实现具体的支付渠道。
-
具体支付模式(PayCypher、PayFaceMode、PayFingerprintMode):实现不同的支付方式。
3.3 代码实现
3.3.1 支付模式接口 (IPayMode)
#include <stdio.h>
#include <stdbool.h>
typedef struct IPayMode IPayMode;
struct IPayMode
{
bool (*security)(IPayMode *payMode, const char *uId); // 安全校验方法
};
bool payCypherSecurity(IPayMode *payMode, const char *uId)
{
printf("密码支付,风控校验:环境安全\n");
return true;
}
bool payFaceModeSecurity(IPayMode *payMode, const char *uId)
{
printf("人脸支付,风控校验:脸部识别\n");
return true;
}
bool payFingerprintModeSecurity(IPayMode *payMode, const char *uId)
{
printf("指纹支付,风控校验:指纹信息\n");
return true;
}
IPayMode payCypher = {payCypherSecurity};
IPayMode payFaceMode = {payFaceModeSecurity};
IPayMode payFingerprintMode = {payFingerprintModeSecurity};
3.3.2 支付抽象类 (Pay)
#include <stdio.h>
#include <string.h>
typedef struct Pay Pay;
typedef struct IPayMode IPayMode;
struct Pay
{
IPayMode *payMode; // 支付模式接口
const char *channel; // 支付渠道
void (*transfer)(Pay *pay, const char *uId, const char *tradeId, double amount); // 划账功能
};
void wxPayTransfer(Pay *pay, const char *uId, const char *tradeId, double amount)
{
printf("微信支付划账开始...\n");
bool security = pay->payMode->security(pay->payMode, uId);
printf("微信支付风险校验:%s,交易号:%s,安全性:%s\n", uId, tradeId, security ? "通过" : "失败");
if (!security)
{
printf("微信支付划账失败!\n");
return;
}
printf("微信支付划账成功!金额:%.2f\n", amount);
}
void zfbPayTransfer(Pay *pay, const char *uId, const char *tradeId, double amount)
{
printf("支付宝支付划账开始...\n");
bool security = pay->payMode->security(pay->payMode, uId);
printf("支付宝支付风险校验:%s,交易号:%s,安全性:%s\n", uId, tradeId, security ? "通过" : "失败");
if (!security)
{
printf("支付宝支付划账失败!\n");
return;
}
printf("支付宝支付划账成功!金额:%.2f\n", amount);
}
void bankPayTransfer(Pay *pay, const char *uId, const char *tradeId, double amount)
{
printf("银行卡支付划账开始...\n");
bool security = pay->payMode->security(pay->payMode, uId);
printf("银行卡支付风险校验:%s,交易号:%s,安全性:%s\n", uId, tradeId, security ? "通过" : "失败");
if (!security)
{
printf("银行卡支付划账失败!\n");
return;
}
printf("银行卡支付划账成功!金额:%.2f\n", amount);
}
void wxPayConstruct(Pay *pay, IPayMode *payMode)
{
pay->payMode = payMode;
pay->channel = "微信支付";
pay->transfer = wxPayTransfer;
}
void zfbPayConstruct(Pay *pay, IPayMode *payMode)
{
pay->payMode = payMode;
pay->channel = "支付宝支付";
pay->transfer = zfbPayTransfer;
}
void bankPayConstruct(Pay *pay, IPayMode *payMode)
{
pay->payMode = payMode;
pay->channel = "银行卡支付";
pay->transfer = bankPayTransfer;
}
3.3.3 测试类
#include <stdio.h>
int main(void)
{
Pay wxPay, zfbPay, bankPay;
// 创建支付渠道
wxPayConstruct(&wxPay, &payFaceMode);
zfbPayConstruct(&zfbPay, &payFingerprintMode);
bankPayConstruct(&bankPay, &payCypher);
// 测试:微信支付,人脸支付
printf("\n测试:微信支付,人脸支付\n");
wxPay.transfer(&wxPay, "wx_00100100", "10001900", 100.0);
// 测试:支付宝支付,指纹支付
printf("\n测试:支付宝支付,指纹支付\n");
zfbPay.transfer(&zfbPay, "zfb_1234567", "567689999999", 200.0);
// 测试:银行卡支付,密码支付
printf("\n测试:银行卡支付,密码支付\n");
bankPay.transfer(&bankPay, "bank_1234567", "987654321", 300.0);
return 0;
}
4. 优缺点比较
4.1 优点:
-
解耦合:通过桥接接口(
IPayMode
)将支付渠道和支付方式解耦,使得系统能够独立扩展新的支付方式和支付渠道。 -
易于扩展:只需要新增一个支付渠道或支付方式,无需修改现有代码,符合 **开闭原则**。
-
避免继承膨胀:通过组合替代继承,避免了继承层次过深,保持了代码的简洁和可维护性。
4.2 缺点:
-
设计复杂:初期设计时需要识别出变化的维度并合理划分接口和类,可能会增加设计和理解的难度。
-
可能会增加类的数量:桥接模式通过组合来替代继承,虽然避免了继承层次爆炸,但也会增加类的数量。
5. 总结
桥接模式特别适用于 **多维度变化的场景**,如支付系统中的支付渠道和支付方式的组合。在 售卖饮料机的嵌入式支付系统 中,桥接模式帮助我们将支付渠道(如微信支付、支付宝支付、银行卡支付)与支付方式(如密码支付、人脸支付、指纹支付)解耦,简化了代码的复杂度,使得系统更加灵活,易于扩展和维护。
通过本文的示例,您可以看到,桥接模式有效地解决了多个维度变化的组合问题,让系统能够在 不修改现有代码 的基础上,轻松扩展新的功能和维度。希望本文能够帮助您理解并在实际开发中运用 桥接模式 来提升代码质量和系统可扩展性。
更多推荐
所有评论(0)