解释说明:将抽象部分与它的实现部分解耦,使得两者都能够独立变化
桥接模式将两个独立变化的维度设计成两个独立的继承等级结构(而不会将两者耦合在一起形成多层继承结构),在抽象层将二者建立起一个抽象关联,该关联关系类似一座桥,将两个独立的等级结构连接起来,故曰“桥接模式”
抽象类(Abstraction):定义抽象类,并包含一个对实现化对象的引用
扩充抽象类(RefinedAbstraction):是抽象化类的子类,实现父类那个中的业务方法,并通过组合关系调用实现化角色中的业务方法
实现类(Implementor):定义实现化角色的接口,供扩展抽象化角色调用
具体实现(ConcreteImplementor):给出实现化角色接口的具体实现
优点:
分离抽象和实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。
在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。
缺点:
桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。
适用场景
如果一个系统需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。
“抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
一个系统存在多个(≥ 2)独立变化的维度,且这多个维度都需要独立进行扩展。
对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
#pragma once
#include <iostream>
// 电器
class IElectricalEquipment
{
public:virtual ~IElectricalEquipment() {}// 打开virtual void PowerOn() = 0;// 关闭virtual void PowerOff() = 0;
};
// 电灯
class Light : public IElectricalEquipment
{
public:// 开灯virtual void PowerOn() override {std::cout << "Light is on." << std::endl;}// 关灯virtual void PowerOff() override {std::cout << "Light is off." << std::endl;}
};
// 风扇
class Fan : public IElectricalEquipment
{
public:// 打开风扇virtual void PowerOn() override {std::cout << "Fan is on." << std::endl;}// 关闭风扇virtual void PowerOff() override {std::cout << "Fan is off." << std::endl;}
};#pragma once
#include "implementor.h"
// 开关
class ISwitch
{
public:ISwitch(IElectricalEquipment* ee) { m_pEe = ee; }virtual ~ISwitch() {}// 打开电器virtual void On() = 0;// 关闭电器virtual void Off() = 0;
protected:IElectricalEquipment* m_pEe;
};
// 拉链式开关
class PullChainSwitch : public ISwitch
{
public:PullChainSwitch(IElectricalEquipment* ee) : ISwitch(ee) {}// 用拉链式开关打开电器virtual void On() override {std::cout << "Switch on the equipment with a pull chain switch." << std::endl;m_pEe->PowerOn();}// 用拉链式开关关闭电器virtual void Off() override {std::cout << "Switch off the equipment with a pull chain switch." << std::endl;m_pEe->PowerOff();}
};
// 两位开关
class TwoPositionSwitch : public ISwitch
{
public:TwoPositionSwitch(IElectricalEquipment* ee) : ISwitch(ee) {}// 用两位开关打开电器virtual void On() override {std::cout << "Switch on the equipment with a two-position switch." << std::endl;m_pEe->PowerOn();}// 用两位开关关闭电器virtual void Off() override {std::cout << "Switch off the equipment with a two-position switch." << std::endl;m_pEe->PowerOff();}
};#include "abstraction.h"
#include "implementor.h"
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif
int main()
{// 创建电器 - 电灯、风扇IElectricalEquipment* light = new Light();IElectricalEquipment* fan = new Fan();/*** 创建开关 - 拉链式开关、两位开关* 将拉链式开关和电灯关联起来,将两位开关和风扇关联起来**/ISwitch* pullChain = new PullChainSwitch(light);ISwitch* twoPosition = new TwoPositionSwitch(fan);// 开灯、关灯pullChain->On();pullChain->Off();// 打开风扇、关闭风扇twoPosition->On();twoPosition->Off();SAFE_DELETE(twoPosition);SAFE_DELETE(pullChain);SAFE_DELETE(fan);SAFE_DELETE(light);getchar();return 0;
}