本文主要的思路和代码,来自于对以下连接的学习和实现:
桥接模式
桥接模式,顾名思义,就像是一座连接两岸的桥梁。在软件开发中,我们可以将桥接模式看作是一座连接抽象部分和实现部分的“桥”,通过这座“桥”,我们可以方便地在抽象部分和实现部分之间进行切换,而不需要关心它们之间的实现细节。
桥接模式的核心作用就是降低系统的耦合度,提高扩展性和可维护性。想象一下你正在修建一座连接两个城市的大桥,如果没有这座桥,你需要绕行很远的距离才能到达对岸。同样地,在软件开发中,如果没有桥接模式,抽象部分和实现部分之间的依赖关系可能会变得非常复杂,导致系统难以扩展和维护。
桥接模式和其他设计模式都是非常有用的工具,它们可以帮助我们更好地组织和管理代码,提高系统的可维护性和可扩展性。在使用这些工具时,我们需要根据具体的需求和场景来选择合适的模式,以最大程度地发挥它们的效用。
桥接模式的应用场景也非常广泛。比如我们正在开发一个电商网站,其中有一个订单管理系统和一个支付系统。这两个系统分别负责订单的处理和支付的操作,但是它们之间的关系非常紧密。如果没有桥接模式,我们需要在订单管理系统和支付系统中都实现相同的逻辑,这显然是不合理的。而如果我们使用桥接模式,可以将订单管理系统和支付系统分别抽象成两个独立的类,并通过一个桥接器来协调它们之间的交互,这样就可以避免代码冗余和耦合度过高的问题。如果我们概括一下桥接模式的使用场景的话,主要有以下几个:
桥接模式的实现方式就像是一座连接不同平台的桥梁,它通过抽象部分和实现部分之间的关联来实现。如果以连接桥梁为例,其大致的步骤为:
抽象部分在桥接模式中起到了至关重要的连接作用。它通过定义接口、封装逻辑、委派工作等方式,将不同的平台进行连接,并帮助客户端与实现部分进行交互。
抽象部分就像是一座桥梁的桥墩,它具体负责了下面的一些内容:
具体部分在桥接模式中同样起到了至关重要的作用。它通过实现抽象部分所定义的方法和属性,完成具体的操作,并帮助客户端与实现部分进行交互。同时,具体部分还可以根据抽象部分的定义,使用不同的实现方式来完成不同的业务逻辑。
具体部分就像是一座桥梁的桥面和支撑结构,它具体负责了下面的一些内容:
综上所述,桥接模式的优点在于它可以帮助我们更好地组织和管理代码,提高系统的可维护性和可扩展性。通过创建与平台无关的类和程序、客户端代码仅与高层抽象部分进行互动、遵循开闭原则以及单一职责原则等特性,桥接模式为我们提供了一个灵活、高效且易于维护的设计方案。
综上所述,桥接模式是一种灵活的设计模式,可以帮助我们更好地组织和管理代码。然而,在使用该模式时也需要注意一些潜在的问题和挑战。就像建造一座桥梁需要考虑许多因素一样,使用桥接模式也需要综合考虑各种因素,以确保系统的正确性和可靠性。
// “抽象部分”定义了两个类层次结构中“控制”部分的接口。它管理着一个指向“实
// 现部分”层次结构中对象的引用,并会将所有真实工作委派给该对象。
class RemoteControl is
protected field device: Device
constructor RemoteControl(device: Device) is
this.device = device
method togglePower() is
if (device.isEnabled()) then
device.disable()
else
device.enable()
method volumeDown() is
device.setVolume(device.getVolume() - 10)
method volumeUp() is
device.setVolume(device.getVolume() + 10)
method channelDown() is
device.setChannel(device.getChannel() - 1)
method channelUp() is
device.setChannel(device.getChannel() + 1)
// 你可以独立于设备类的方式从抽象层中扩展类。
class AdvancedRemoteControl extends RemoteControl is
method mute() is
device.setVolume(0)
// “实现部分”接口声明了在所有具体实现类中通用的方法。它不需要与抽象接口相
// 匹配。实际上,这两个接口可以完全不一样。通常实现接口只提供原语操作,而
// 抽象接口则会基于这些操作定义较高层次的操作。
interface Device is
method isEnabled()
method enable()
method disable()
method getVolume()
method setVolume(percent)
method getChannel()
method setChannel(channel)
// 所有设备都遵循相同的接口。
class Tv implements Device is
// ……
class Radio implements Device is
// ……
// 客户端代码中的某个位置。
tv = new Tv()
remote = new RemoteControl(tv)
remote.togglePower()
radio = new Radio()
remote = new AdvancedRemoteControl(radio)
#include
#include
/**
* The Implementation defines the interface for all implementation classes. It
* doesn't have to match the Abstraction's interface. In fact, the two
* interfaces can be entirely different. Typically the Implementation interface
* provides only primitive operations, while the Abstraction defines higher-
* level operations based on those primitives.
*/
class Implementation
{
public:
virtual ~Implementation() {}
virtual std::string OperationImplementation() const = 0;
};
/**
* Each Concrete Implementation corresponds to a specific platform and
* implements the Implementation interface using that platform's API.
*/
class ConcreteImplementationA : public Implementation
{
public:
std::string OperationImplementation() const override
{
return "ConcreteImplementationA: Here's the result on the platform A.\n";
}
};
class ConcreteImplementationB : public Implementation
{
public:
std::string OperationImplementation() const override
{
return "ConcreteImplementationB: Here's the result on the platform B.\n";
}
};
/**
* The Abstraction defines the interface for the "control" part of the two class
* hierarchies. It maintains a reference to an object of the Implementation
* hierarchy and delegates all of the real work to this object.
*/
class Abstraction
{
/**
* @var Implementation
*/
protected:
Implementation *implementation_;
public:
Abstraction(Implementation *implementation) : implementation_(implementation)
{
}
virtual ~Abstraction()
{
}
virtual std::string Operation() const
{
return "Abstraction: Base operation with:\n" +
this->implementation_->OperationImplementation();
}
};
/**
* You can extend the Abstraction without changing the Implementation classes.
*/
class ExtendedAbstraction : public Abstraction
{
public:
ExtendedAbstraction(Implementation *implementation) : Abstraction(implementation)
{
}
std::string Operation() const override
{
return "ExtendedAbstraction: Extended operation with:\n" +
this->implementation_->OperationImplementation();
}
};
/**
* Except for the initialization phase, where an Abstraction object gets linked
* with a specific Implementation object, the client code should only depend on
* the Abstraction class. This way the client code can support any abstraction-
* implementation combination.
*/
void ClientCode(const Abstraction &abstraction)
{
// ...
std::cout << abstraction.Operation();
// ...
}
/**
* The client code should be able to work with any pre-configured abstraction-
* implementation combination.
*/
void BridgeExample()
{
Implementation *implementation = new ConcreteImplementationA;
Abstraction *abstraction = new Abstraction(implementation);
ClientCode(*abstraction);
std::cout << std::endl;
delete implementation;
delete abstraction;
implementation = new ConcreteImplementationB;
abstraction = new ExtendedAbstraction(implementation);
ClientCode(*abstraction);
delete implementation;
delete abstraction;
}
#ifndef _REMOTE_EXAMPLE_H_
#define _REMOTE_EXAMPLE_H_
// The abstract Device class.
class Device
{
public:
virtual bool isEnabled() = 0;
virtual void enable() = 0;
virtual void disable() = 0;
virtual int getVolume() = 0;
virtual void setVolume(int volume) = 0;
virtual int getChannel() = 0;
virtual void setChannel(int channel) = 0;
protected:
virtual bool checkIsValidVolume(int volume) const = 0;
virtual bool checkIsValidChannel(int channel) const = 0;
};
class RemoteControl
{
protected:
Device* m_pDevice = nullptr;
public:
RemoteControl(Device* pDevice);
void togglePower();
void volumeDown();
void volumeUp();
void channelDown();
void channelUp();
};
class AdvancedRemoteControl : public RemoteControl
{
public:
void mute();
};
class TVDevice : public Device
{
public:
TVDevice(bool isEnabled = false, int volume = 1, int channel = 0);
bool isEnabled() override;
void enable() override;
void disable() override;
int getVolume() override;
void setVolume(int volume) override;
int getChannel() override;
void setChannel(int channel) override;
void printDeviceInfo();
private:
bool checkIsValidVolume(int volume) const override;
bool checkIsValidChannel(int channel) const override;
private:
bool m_isEnabled = false;
int m_volume = 1;
int m_channel = 0;
};
class RadioDevice : public Device
{
public:
RadioDevice(bool isEnabled = false, int volume = 1, int channel = 0);
bool isEnabled() override;
void enable() override;
void disable() override;
int getVolume() override;
void setVolume(int volume) override;
int getChannel() override;
void setChannel(int channel) override;
void printDeviceInfo();
private:
bool checkIsValidVolume(int volume) const override;
bool checkIsValidChannel(int channel) const override;
private:
bool m_isEnabled = false;
int m_volume = 1;
int m_channel = 0;
};
class RemoteExample
{
public:
static void TVControlCase();
static void RadioControlCase();
};
#endif // _REMOTE_EXAMPLE_H_
#include "remote_example.h"
#include
namespace
{
constexpr int TV_VOLUME_MAX = 100;
constexpr int TV_CHANNEL_MAX = 256;
constexpr int RADIO_VOLUME_MAX = 200;
constexpr int RADIO_CHANNEL_MAX = 512;
}
RemoteControl::RemoteControl(Device* pDevice)
: m_pDevice(pDevice)
{
}
void RemoteControl::togglePower()
{
if (m_pDevice->isEnabled()) {
m_pDevice->disable();
} else {
m_pDevice->enable();
}
}
void RemoteControl::volumeDown()
{
m_pDevice->setVolume(m_pDevice->getVolume() - 10);
}
void RemoteControl::volumeUp()
{
m_pDevice->setVolume(m_pDevice->getVolume() + 10);
}
void RemoteControl::channelDown()
{
m_pDevice->setChannel(m_pDevice->getChannel() - 1);
}
void RemoteControl::channelUp()
{
m_pDevice->setChannel(m_pDevice->getChannel() + 1);
}
void AdvancedRemoteControl::mute()
{
m_pDevice->setVolume(0);
}
TVDevice::TVDevice(bool isEnabled /*= true*/, int volume /*= 1*/, int channel /*= 0*/)
: m_isEnabled(isEnabled)
, m_volume(volume)
, m_channel(channel)
{
}
bool TVDevice::isEnabled()
{
return m_isEnabled;
}
void TVDevice::enable()
{
m_isEnabled = true;
}
void TVDevice::disable()
{
m_isEnabled = false;
}
int TVDevice::getVolume()
{
return m_volume;
}
void TVDevice::setVolume(int volume)
{
if (checkIsValidVolume(volume))
{
m_volume = volume;
}
else
{
std::cout << "Error volume for this TV Device!" << std::endl;
}
}
int TVDevice::getChannel()
{
return m_channel;
}
void TVDevice::setChannel(int channel)
{
if (checkIsValidChannel(channel))
{
m_channel = channel;
}
else
{
std::cout << "Error channel for this TV Device!" << std::endl;
}
}
void TVDevice::printDeviceInfo()
{
std::cout << "TVDevice Info : Volume :"
<< m_volume << '\t' << "Channel : " << m_channel << std::endl;
}
bool TVDevice::checkIsValidVolume(int volume) const
{
return (volume >= 0 && volume <= TV_VOLUME_MAX) ? true : false;
}
bool TVDevice::checkIsValidChannel(int channel) const
{
return (channel >= 0 && channel <= TV_CHANNEL_MAX) ? true : false;
}
RadioDevice::RadioDevice(bool isEnabled /*= true*/, int volume /*= 1*/, int channel /*= 0*/)
: m_isEnabled(isEnabled)
, m_volume(volume)
, m_channel(channel)
{
}
bool RadioDevice::isEnabled()
{
return m_isEnabled;
}
void RadioDevice::enable()
{
m_isEnabled = true;
}
void RadioDevice::disable()
{
m_isEnabled = false;
}
int RadioDevice::getVolume()
{
return m_volume;
}
void RadioDevice::setVolume(int volume)
{
if (checkIsValidVolume(volume))
{
m_volume = volume;
}
else
{
std::cout << "Error volume for this TV Device!" << std::endl;
}
}
int RadioDevice::getChannel()
{
return m_channel;
}
void RadioDevice::setChannel(int channel)
{
if (checkIsValidChannel(channel))
{
m_channel = channel;
}
else
{
std::cout << "Error channel for this TV Device!" << std::endl;
}
}
bool RadioDevice::checkIsValidVolume(int volume) const
{
return (volume >= 0 && volume <= RADIO_VOLUME_MAX) ? true : false;
}
bool RadioDevice::checkIsValidChannel(int channel) const
{
return (channel >= 0 && channel <= RADIO_CHANNEL_MAX) ? true : false;
}
void RadioDevice::printDeviceInfo()
{
std::cout << "RadioDevice Info : Volume :"
<< m_volume << '\t' << "Channel : " << m_channel << std::endl;
}
void RemoteExample::TVControlCase()
{
std::cout << "\nTV Device example case start." << std::endl;
TVDevice tv;
RemoteControl remoteTv(&tv);
remoteTv.togglePower();
tv.printDeviceInfo();
remoteTv.channelUp();
std::cout << "After TV channel up:" << std::endl;
tv.printDeviceInfo();
remoteTv.volumeUp();
std::cout << "After TV volume Up:" << std::endl;
tv.printDeviceInfo();
AdvancedRemoteControl adRemote(&tv);
adRemote.mute();
std::cout << "After TV is muted:" << std::endl;
tv.printDeviceInfo();
std::cout << "\nTV Device example case end." << std::endl;
}
void RemoteExample::RadioControlCase()
{
std::cout << "\nRadio Device example case start." << std::endl;
RadioDevice radio;
RemoteControl remoteRadio(&radio);
remoteRadio.togglePower();
radio.printDeviceInfo();
remoteRadio.channelUp();
std::cout << "After Radio channel up:" << std::endl;
radio.printDeviceInfo();
remoteRadio.volumeUp();
std::cout << "After Radio volume Up:" << std::endl;
radio.printDeviceInfo();
AdvancedRemoteControl adRemote(&radio);
adRemote.mute();
std::cout << "After Radio is muted:" << std::endl;
radio.printDeviceInfo();
std::cout << "\nRadio Device example case end." << std::endl;
}
相关代码由以下类组成:
Implementation
:这是一个抽象基类,定义了所有实现类的接口。它有一个纯虚函数 OperationImplementation()
。
ConcreteImplementationA
和 ConcreteImplementationB
:这两个类是 Implementation
的具体实现,分别对应平台A和平台B。它们实现了 OperationImplementation()
方法,返回特定平台的结果。
Abstraction
:这个类定义了控制部分的接口,并维护了一个对 Implementation
类的对象的引用。它有一个虚函数 Operation()
,该函数通过委托给 implementation_
对象来执行实际工作。
ExtendedAbstraction
:这是 Abstraction
的子类,扩展了其功能。它在 Operation()
中添加了一些额外的操作。
ClientCode
和 BridgeExample
:这两个函数/方法用于客户端代码,与抽象和实现类进行交互。
这些类的角色如下:
Implementation
:定义了所有实现类的接口。ConcreteImplementationA
和 ConcreteImplementationB
:实现了 Implementation
接口,提供了特定平台的实现。Abstraction
:作为控制部分的接口,封装了对 Implementation
对象的引用,并提供了基本的操作。ExtendedAbstraction
:扩展了 Abstraction
的功能。ClientCode
和 BridgeExample
:客户端代码,与抽象和实现类进行交互。模式中的各个元素以以下方式相互关联:
Abstraction
类包含一个指向 Implementation
类的指针,并通过该指针调用 OperationImplementation()
方法。ExtendedAbstraction
类继承自 Abstraction
类,并重写了 Operation()
方法,增加了额外的操作。ClientCode
函数接受一个 Abstraction
类的引用,并通过该引用调用 Operation()
方法。BridgeExample
函数演示了如何使用不同的 Abstraction
和 Implementation
组合创建对象,并通过 ClientCode
函数调用相应的操作。相关代码由以下类组成:
Device
:这是一个抽象类,定义了一些设备共有的属性和方法,如检查设备是否启用、获取和设置音量和频道等。
RemoteControl
:这是一个基类,它有一个指向Device
类的指针,并定义了一些远程控制设备的基本操作,如切换电源、调整音量和频道等。
AdvancedRemoteControl
:这是RemoteControl
的子类,增加了静音功能。
TVDevice
和 RadioDevice
:这两个类都继承自Device
类,分别代表电视设备和无线电设备。它们都实现了Device
类中的虚函数,并添加了一些特定于设备的属性和方法,如打印设备信息等。
RemoteExample
:这是一个包含两个静态方法的类,用于在其他地方调用以执行特定的远程控制案例。
这些类的角色如下:
Device
:作为所有设备的基类,定义了通用的设备属性和方法。RemoteControl
:作为远程控制的基类,提供了一些设备的基本操作。AdvancedRemoteControl
:扩展了远程控制的功能,包括静音。TVDevice
和 RadioDevice
:这两个类代表了具体的设备类型,它们继承了Device
类,并实现了Device
类中的方法,添加了特定于设备的属性和方法。RemoteExample
:包含了两个静态方法,用于在其他地方执行特定的远程控制案例。