Bridge 桥接模式
引例
- 一个模块在m个平台中实现,基于平台又有n种业务抽象
class Messager { public: virtual void Login(string username, string password) = 0; virtual void SendMessage(string message) = 0; virtual void SendPicture(Image image) = 0; virtual void PlaySound() = 0; virtual void DrawShape() = 0; virtual void WriteText() = 0; virtual void Connect() = 0; virtual ~Messager(){} }; // 平台实现,假设m个平台 // pc 平台 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() { ... } }; // 业务抽象 假设n种业务 // pc平台精简版 class PCMessagerLite : public PCMessagerBase { public: virtual void Login(string username, string password) { PCMessageBase::Connect(); ...... } virtual void SendMessage(string message) { PCMessagerBase::WriteText(); ...... } virtual void SendPicture(Image image) { PCMessagerBase::DrawShape(); ...... } }; // pc平台完整版,相比精简版多一些额外操作 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 + m + m *n
- 将Messager类做一个拆分;使用装饰器模式 精简 平台部分
class Messager
{
public:
virtual void Login(string username, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(Image image) = 0;
virtual ~Messager(){}
};
class MessagerImp
{
public:
virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;
virtual ~MessagerImp(){}
};
// 平台实现,假设m个平台
// pc 平台
class PCMessagerBase : public MessagerImp
{
public:
virtual void PlaySound()
{
...
}
virtual void DrawShape()
{
...
}
virtual void WriteText()
{
...
}
virtual void Connect()
{
...
}
};
// 移动平台
class MobileMessagerBase : public MessagerImp
{
public:
virtual void PlaySound()
{
...
}
virtual void DrawShape()
{
...
}
virtual void WriteText()
{
...
}
virtual void Connect()
{
...
}
};
// 业务抽象 假设n种业务
// 平台精简版
class MessagerLite : public Messager
{
// 下面这种写法不对,PCMessagerBase没有完全实现Messager中的虚函数
//Messager* messager; // new PCMessagerBase() / new MobileMessagerBase()
MessagerImp* messagerImp;
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
{
MessagerImp* messagerImp;
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()
{
Messager *m = ...
}
- 马丁弗勒在重构中说,代码结构中在子类中有同样的字段,将字段往上提,提到父类中
class Messager
{
protected:
MessagerImp* messagerImp;
public:
Messager(MessagerImp* msgImp) : messagerImp(msgImp){}
virtual void Login(string username, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(Image image) = 0;
virtual ~Messager(){}
};
class MessagerImp
{
public:
virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;
virtual ~MessagerImp(){}
};
// 平台实现,假设m个平台
// pc 平台
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()
{
...
}
};
// 业务抽象 假设n种业务
// 平台精简版
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()
{
// Message *m = new MobileMessagerPerfect(); // 编译时装配
// 运行时装配
MessagerImp* mi = new MobileMessagerImp();
Messager *mp = new MessagerPerfect(mi);
}
动机 Motivation
- 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个维度的变化。
- 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?
模式定义
将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。
结构
红色为稳定部分,蓝色为变化部分。
上文代码中,Messager相当于图中的Abstraction,MessagerImp相当于Implementor。MessagerLite、MessagerPerfect相当于RefinedAbstraction;PCMessagerImp相当于ConcreteImplementorA,MobileMessagerImp相当于ConcreteImplementorB。
要点总结
- Bridge 桥接模式使用**“对象间的组合关系”**(抽象部分 含有 实现部分 的指针)解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,即“子类化”它们。
- Bridge桥接模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(一个类只有一个变化的原因),复用性比较差,桥接模式是比多继承方案更好的解决方法。
- 桥接模式的应用一般在“两个非常强的变化维度”,有时一个类也有多于两个的变化维度,这时可以使用Brideg桥接模式的扩展模式。(将变化维度部分抽象出来即为实现部分。可以包含多个 实现部分的指针)。