[设计模式]桥模式
1. 桥模式的设计理念
“桥模式”与“装饰模式”一样,是对于设计模式中的“单一职责”来进行修改的,其中“装饰模式”是对于很多附加功能的修改,而桥模式是针对多维度。
桥模式是针对多维度实现装配组合的,举个例子,两个维度,m*n,则要至少实现m*n个类;而如果使用桥模式,在编译时去自由组合,只需要实现m+n个类。
下面的就是很形象的,其存在两个维度:多平台(安卓,MacOs,Windows)、多版本(简约版,完美版)。
而使用桥模式,将其拆分为两个维度,根据需要来编译时自由组合不同的版本,这样大大减少代码量。
2. 反例
如下代码,是一个很典型的反例,可以看出生成了大量的类来满足不同版本的需求
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(){} }; //平台实现 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(); }
3. 根据桥模式设计的代码
如下,假设QQ存在如上所示的六种版本,桥模式的代码如下,可以看到其非常简约,其一个维度中+1只需要开发一个类即可,而不用桥模式的代码需要增加m(n)个类。
#include <stdio.h> #include <iostream> #include <windows.h> using namespace std; //功能 class QqFunc { public: virtual void SendMessage() = 0; // 发送消息 virtual void SendPicture() = 0; // 发送图片 virtual ~QqFunc() {} }; // 平台维度基类 class QqPlatform { public: QqFunc* qFunc; // 两个维度在这里建立连接 QqPlatform(QqFunc* p) :qFunc(p) {} // 初始化实现 virtual void Login() = 0; // 登录 virtual void Logon() = 0; // 注册 virtual ~QqPlatform(){} }; // 功能1 - 简约版 class QqLite : public QqFunc { public: void SendMessage() { cout << "简约版发送消息功能" << endl; } void SendPicture() { cout << "简约版发送图片功能" << endl; } }; // 功能2 - 完美版 class QqPerfect : public QqFunc { public: void SendMessage() { cout << "完美版发送消息功能" << endl; } void SendPicture() { cout << "完美版发送图片功能" << endl; } }; // 平台1 - Windows平台 class QqWindows :public QqPlatform { public: QqWindows(QqFunc* p) : QqPlatform(p) {} virtual void Login() { cout << "Windows平台下登录" << endl; } virtual void Logon() { cout << "Windows平台下注册" << endl; } }; // 平台2 - Macos平台 class QqMacos :public QqPlatform { public: QqMacos(QqFunc* p) : QqPlatform(p) {} virtual void Login() { cout << "QqMacos平台下登录" << endl; } virtual void Logon() { cout << "QqMacos平台下注册" << endl; } }; int main() { QqLite* qLite = new QqLite(); // 轻版 QqMacos* qMacos = new QqMacos(qLite); // Macos平台 qMacos->Login(); qMacos->qFunc->SendPicture(); }