赞
踩
角色定义:
工作原理:
#include <iostream> // 实现化角色接口 class Implementor { public: virtual ~Implementor() {} virtual void operationImpl() = 0; // 定义操作接口 }; // 具体实现化角色A class ConcreteImplementorA : public Implementor { public: void operationImpl() override { std::cout << "ConcreteImplementorA 的 operationImpl()" << std::endl; } }; // 具体实现化角色B class ConcreteImplementorB : public Implementor { public: void operationImpl() override { std::cout << "ConcreteImplementorB 的 operationImpl()" << std::endl; } }; // 抽象化角色 class Abstraction { protected: Implementor* _implementor; public: Abstraction(Implementor* impl) : _implementor(impl) {} virtual ~Abstraction() { delete _implementor; } virtual void operation() = 0; // 定义抽象操作 }; // 具体抽象化角色 class RefinedAbstraction : public Abstraction { public: RefinedAbstraction(Implementor* impl) : Abstraction(impl) {} void operation() override { std::cout << "RefinedAbstraction 调用 operation..." << std::endl; _implementor->operationImpl(); // 委托实现化角色执行操作 } }; int main() { Abstraction* absA = new RefinedAbstraction(new ConcreteImplementorA()); absA->operation(); Abstraction* absB = new RefinedAbstraction(new ConcreteImplementorB()); absB->operation(); delete absA; delete absB; return 0; }
在这个例子中,Abstraction
是抽象化角色,RefinedAbstraction
是具体抽象化角色,Implementor
是实现化角色接口,ConcreteImplementorA
和ConcreteImplementorB
是具体实现化角色。通过改变构造Abstraction
时传入的Implementor
的不同实现,我们可以轻松切换不同的行为方式。
桥接模式的核心价值在于它能分离抽象和实现,让两者可以独立演化。下面是对上述代码实例的进一步解释:
operation()
,但不提供具体实现。它通过维持一个指向Implementor
的指针来间接使用其实现。class Abstraction {
protected:
Implementor* _implementor;
public:
// 构造函数接收一个Implementor对象的指针
Abstraction(Implementor* impl) : _implementor(impl) {}
virtual ~Abstraction() { delete _implementor; }
// 定义抽象操作
virtual void operation() = 0;
};
Abstraction
,在operation()
中调用了_implementor
的operationImpl()
方法,这样就把具体实现细节交给了实现化角色。class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(Implementor* impl) : Abstraction(impl) {}
// 实现抽象操作,调用Implementor的实现
void operation() override {
std::cout << "RefinedAbstraction 调用 operation..." << std::endl;
_implementor->operationImpl();
}
};
operationImpl()
,它是抽象化角色依赖的具体操作。class Implementor {
public:
virtual ~Implementor() {}
// 实现化角色的接口
virtual void operationImpl() = 0;
};
operationImpl()
的不同实现。class ConcreteImplementorA : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorA 的 operationImpl()" << std::endl;
}
};
class ConcreteImplementorB : public Implementor {
public:
void operationImpl() override {
std::cout << "ConcreteImplementorB 的 operationImpl()" << std::endl;
}
};
在main函数中,我们可以根据需要为Abstraction
实例化不同的Implementor
对象,从而达到在运行时动态改变系统行为的目的,这就是桥接模式的关键所在。通过这种方式,抽象与实现得以解耦,各自可以独立扩展而不影响对方。
:
优点:
适用场景:
总结来说,桥接模式在设计中鼓励关注点分离,让抽象和实现各自独立演进,提高了代码的可维护性和复用性。在实际编程过程中,尤其是在设计复杂的面向对象系统时,合理运用桥接模式可以显著提升软件的设计质量。
图形界面库:图形界面库通常有多种外观(如按钮、菜单等)和多种平台实现(Windows、Mac、Linux等)。桥接模式可以使抽象外观接口独立于各个平台的具体实现,方便在不同平台上复用相同的外观设计。
日志系统:日志系统可能需要支持不同的日志级别(如Debug、Info、Error等)和不同的输出目的地(如控制台、文件、数据库等)。桥接模式可以将日志级别抽象出来,同时将输出目的地作为一个独立的维度,使得日志系统可以在不修改原有代码的基础上轻易更换日志级别或输出目的地。
数据库驱动:数据库驱动程序可能需要支持不同的数据库(MySQL、Oracle、SQL Server等)和不同的操作(查询、插入、删除、更新等)。桥接模式可以将数据库操作抽象成统一的接口,而具体的数据库操作由不同的实现类负责,这样就能灵活地替换或升级数据库驱动。
图像处理库:图像处理库可能需要支持多种图像格式(JPEG、PNG、GIF等)和多种处理操作(缩放、旋转、裁剪等)。桥接模式可以将图像处理操作抽象化,并与各种图像格式的读写实现解耦,便于添加新的格式支持或处理功能。
总之,桥接模式在面对抽象和实现之间需要独立扩展的问题时,能够帮助我们构建更加灵活、易于维护和扩展的设计方案。在实际开发中,识别出可能需要桥接模式的场景并正确运用,能够显著提升系统的可维护性和可扩展性。
另外,桥接模式也适用于以下情况:
网络通信框架:在网络通信框架中,抽象接口可以定义诸如发送消息、接收消息等功能,而具体实现可以包括TCP、UDP、WebSocket等多种协议。这样,上层应用只需关注消息的发送和接收逻辑,而无需关心底层通信协议的具体实现。
多语言本地化:在国际化应用中,可以将界面的逻辑(如按钮、标签、提示信息等)与具体语言环境(如英文、中文、法文等)分离,通过桥接模式使得在切换不同语言环境时,仅需替换具体的本地化实现即可。
硬件驱动程序:对于硬件设备(如打印机、扫描仪等),抽象接口可以定义一系列设备操作,而具体实现可以针对不同的厂商和型号。这样,即使更换了硬件设备,只要新设备遵循同一接口规范,应用也能无缝对接。
支付系统:支付系统可能需要对接多种支付渠道(如支付宝、微信支付、银行卡支付等),并且每种支付渠道的操作流程各不相同。桥接模式可以将支付操作抽象化,而将具体支付渠道的处理逻辑放在各自的实现类中。
桥接模式不仅限于以上场景,它强调的是将抽象部分与实现部分相分离,使其可以独立变化。在软件工程实践中,遇到类似的多维度变化需求时,都应该考虑是否可以采用桥接模式进行设计。
python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)
50个开发必备的Python经典脚本(41-50)
————————————————
最后我们放松一下眼睛
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。