c++ 设计模式7 (Bridge 桥模式)

4.2 Bridge 桥模式

动机:

由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度。

代码示例:

实现一个Messager,含有基本功能PlaySound,Connect等,并有PC、Mobile不同的平台实现 和 精简、完美等不同业务功能的版本

实现方法1:

Bridge1.cpp

类的个数:1 + n + m*n,数量巨大且不同类之中有大量重复

重构见方法2

 class Messager{
public:
virtual void Login(string username, string password)=;
virtual void SendMessage(string message)=;
virtual void SendPicture(Image image)=; virtual void PlaySound()=;
virtual void DrawShape()=;
virtual void WriteText()=;
virtual void Connect()=; virtual ~Messager(){}
}; //平台实现 class PCMessagerBase : public Messager{
public: virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
}; class MobileMessagerBase : public Messager{
public: virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
}; //业务抽象 class PCMessagerLite : public PCMessagerBase {
public: virtual void Login(string username, string password){ PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ PCMessagerBase::DrawShape();
//........
}
}; class PCMessagerPerfect : public PCMessagerBase {
public: virtual void Login(string username, string password){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ PCMessagerBase::PlaySound();
//********
PCMessagerBase::DrawShape();
//........
}
}; class MobileMessagerLite : public MobileMessagerBase {
public: virtual void Login(string username, string password){ MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ MobileMessagerBase::DrawShape();
//........
}
}; class MobileMessagerPerfect : public MobileMessagerBase {
public: virtual void Login(string username, string password){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::Connect();
//........
}
virtual void SendMessage(string message){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::WriteText();
//........
}
virtual void SendPicture(Image image){ MobileMessagerBase::PlaySound();
//********
MobileMessagerBase::DrawShape();
//........
}
}; void Process(){
//编译时装配
Messager *m =
new MobileMessagerPerfect();
}

重构步骤:

1.继承转组合,将PCMessagerBase,Mobilemessager声明为字段;

 class PCMessagerLite  {
PCMessagerBase *messager;
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
}; class PCMessagerLite {
MobileMessagerBase *messager;
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
};

2.观察上述两个类,发现只有 *messager 声明不同,故采用基类声明,运行时多态调用方式,创建不同的 PCMessagerBase,Mobilemessager;

  class PCMessagerLite  {
Messager *messager; // = new PCMessagerBase()或 MobileMessagerBase()
public: virtual void Login(string username, string password){ messager -> Connect();
//........
}
virtual void SendMessage(string message){ messager -> WriteText();
//........
}
virtual void SendPicture(Image image){ messager -> DrawShape();
//........
}
};

3.考虑步骤2的代码,Messager类是纯虚基类(抽象类),不能实例化,故= new ...不成立。

分析产生这种状况的原因,是Login,SendPicture等与平台实现相关的方法,和PlaySound,DrawShape等与业务功能相关的方法不应该在一个类里。

将其拆分,得到MessagerImp类。

同时将MessagerLite,MessagerPerfect类中相同的MesseagerImp字段提到父类Messager,得到重构后的代码

注意运行时装配

 class Messager{
protected:
MessagerImp* messagerImp;//...
public:
virtual void Login(string username, string password)=;
virtual void SendMessage(string message)=;
virtual void SendPicture(Image image)=; virtual ~Messager(){}
}; class MessagerImp{
public:
virtual void PlaySound()=;
virtual void DrawShape()=;
virtual void WriteText()=;
virtual void Connect()=; virtual MessagerImp(){}
}; //平台实现 n
class PCMessagerImp : public MessagerImp{
public: virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
}; class MobileMessagerImp : public MessagerImp{
public: virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
}; //业务抽象 m //类的数目:1+n+m class MessagerLite :public Messager { public: virtual void Login(string username, string password){ messagerImp->Connect();
//........
}
virtual void SendMessage(string message){ messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){ messagerImp->DrawShape();
//........
}
}; class MessagerPerfect :public Messager { public: virtual void Login(string username, string password){ messagerImp->PlaySound();
//********
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){ messagerImp->PlaySound();
//********
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){ messagerImp->PlaySound();
//********
messagerImp->DrawShape();
//........
}
}; void Process(){
//运行时装配
MessagerImp* mImp=new PCMessagerImp();
Messager *m =new Messager(mImp);
}

 模式定义:

将抽象部分(业务功能)与实现部分(平台实现)分离,使他们都可以独立地变化。

类图:

c++ 设计模式7 (Bridge 桥模式)

要点总结:

Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象的实现可以沿着各自的维度来变化。所谓抽象和实现研制各自维度的变化,即“子类化”他们。

Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个雷只有一个变化的原因),复用性较差。Bridge模式是比多继承更好的解决方案。

Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也有多余两个的变化维度,这是可以使用Bridge的扩展模式。

上一篇:tinypng的python批量压缩图片功能


下一篇:使用Python的PIL模块来进行图片对比