网站做的和别人一样违法,公众号开发微商城,微信公众平台开发者是什么,万网官网1、定义与动机
桥模式定义#xff1a;将抽象部分#xff08;业务功能#xff09;与实现部分#xff08;平台实现#xff09;分离#xff0c;使他们可以独立地变化引入动机#xff1a; 由于某些类型的固有的实现逻辑#xff0c;使得它们具有两个变化的维度#xff0c;…1、定义与动机
桥模式定义将抽象部分业务功能与实现部分平台实现分离使他们可以独立地变化引入动机 由于某些类型的固有的实现逻辑使得它们具有两个变化的维度乃至多个维度的变化如何应对这种“多维度的变化”如何利用面向对象技术来使用类型可以轻松地沿着两个乃至多个方向变化二部引入额外的复杂度
2、案例分析
假设现在存在这样一个需求
有一个消息发送器Messager里面有七个方法 大致需要完成登录、发送文本消息、发送图片消息、播放声音、建立连接等同时由于存在不同的终端设备例如手机、电脑、pad等他们的这些实现方式肯定会存在一定的不同并且对于同一种设备存在不同的功能组合问题例如发送图片、消息之前播放声音等。
2.1、首先设计一个抽象接口
根据上面所提出的需求可以写出如下的接口代码函数都是纯虚函数和虚函数组成
class Messager{
public:virtual void Login() 0;virtual void SendMessage() 0;virtual void SendPicture() 0;virtual void PlaySound() 0;virtual void DrawShape() 0;virtual void WriteText() 0;virtual void Connect() 0;virtual ~Messager(){}
};2.2、针对不同的终端平台编码设计
例如针对PC、手机…平台设计它们的是如何发送文本、画图、播放声音、建立网络通信连接的代码但是这些Base类依然是一个抽象基类因为存在一些纯虚函数没有实现因此其本身也是一个抽象类
// PC平台实现抽象类没有完全实现完毕所有的纯虚函数
class PCMessagerBase: public Messager{
public:virtual void PlaySound(){// *****}virtual void DrawShape(){// *****}virtual void WriteText(){// *****}virtual void Connect(){// *****}
}// Mobile平台实现抽象类没有完全实现完毕所有的纯虚函数
class MobileMessagerBase: public Messager{
public:virtual void PlaySound(){// *****}virtual void DrawShape(){// *****}virtual void WriteText(){// *****}virtual void Connect(){// *****}
}2.3、针对同平台不同量级的实现
PCMessagerLite轻量级实现该实现类只完成最基本的功能普通登录、发送图片文本消息PCMessagerPerfect完美级实现在执行这些操作之前可以辅助带一些播放声音等额外的功能
class PCMessagerLite: public PCMessagerBase{
public:virtual void Login(){PCMessagerBase::Connect();// ******}virtual void SendMessage(){PCMessagerBase::WriteText();// ******}virtual void SendPicture(){PCMessagerBase::DrawShape();// ******}
};class PCMessagerPerfect: public PCMessagerBase{
public:virtual void Login(){PCMessagerBase::PlaySound();PCMessagerBase::Connect();// ******}virtual void SendMessage(){PCMessagerBase::PlaySound();PCMessagerBase::WriteText();// ******}virtual void SendPicture(){PCMessagerBase::PlaySound();PCMessagerBase::DrawShape();// ******}
};/* MobileMessagerLite、MobileMessagerPerfect的实现如上略过
*/2.4、分析 很明显针对上面的代码一眼就能看出存在大量的代码重复PCMessagerLite和MobileMessagerLite的代码区别完全就在于类名不同、继承的Base类不同。 这一问题很好解决首先把继承变成组合把继承的Base类组合到Lite和Perfect类中 此时只是子类不同由于子类都来自同一个基类Messager那么可以使用多态进行成员声明类型的改变。 最后在使用时动态的传入所需要的不同平台的实现即可。 这样实现会导致一个类的急剧膨胀假设只有1个Messager的接口、n个Base类、那么不同量级的实现是n * m的总体是一个 1 n n * m … 这一点和装饰器模式很像不过装饰器模式是一个阶乘的爆炸但这里的工作量也不低
3、桥模式
针对上面所发现的弊端进行改进首先可以进行的改进
3.1、改进一
将继承改成组合的方式可以很容易的写出PCMessagerLite、MobileMessagerLite的实现代码
class PCMessagerLite{
private:PCMessagerBase* pcMessagerBase;
public:virtual void Login(){pcMessagerBase-Connect();// ******}virtual void SendMessage(){pcMessagerBase-WriteText();// ******}virtual void SendPicture(){pcMessagerBase-DrawShape();// ******}
};class MobileMessagerLite{
private:MobileMessagerBase* mobileMessagerBase;
public:virtual void Login(){mobileMessagerBase-Connect();// ******}virtual void SendMessage(){mobileMessagerBase-WriteText();// ******}virtual void SendPicture(){mobileMessagerBase-DrawShape();// ******}
};3.2、改进二
然后其实可以将PCMessagerLite、MobileMessagerLite提炼成一个代码这两份代码核心不点在于各自做组合的对象不同然而恰巧不巧的事它们所组合的对象都来自同一个基类因此可以提炼成MessagerLite代码
class MessagerLite{
private:Messager* messager;
public:MessagerLite(Messager *msg): messager(msg){}virtual void Login(){messager-Connect();// ******}virtual void SendMessage(){messager-WriteText();// ******}virtual void SendPicture(){messager-DrawShape();// ******}
};但是写完这个代码会有一个问题基类PCMessagerBase和基类MobileMessagerBase是抽象类没有完全实现所有的纯虚函数而抽象类是无法实例化对象的因此这个代码是有问题的无法过编译。 仔细分析问题核心所在点 一路下来我们只在最后不同量级的代码编写实现Messager抽象类的login、SendMessage、SendPicture三个纯虚函数之前的那些Base基类并没有实现这三个方法才导致它们依然是一个抽象类所以问题的核心点Messager抽象类的接口方法太多官方一点的术语职责不够单一违背单一职责原则
3.3、完美改进三
为了解决单一职责问题可以将Messager抽象接口的拆成两个抽象接口Base类继承实现一个接口不同量级实现一个接口然后组合Base类的指针这里动态传入Base类不同的指针
class Messager{
public:virtual void Login() 0;virtual void SendMessage() 0;virtual void SendPicture() 0;virtual ~Messager(){}
};class MessagerImpl{virtual void PlaySound() 0;virtual void DrawShape() 0;virtual void WriteText() 0;virtual void Connect() 0;
};// PC平台实现
class PCMessagerBase: public MessagerImpl{
public:virtual void PlaySound(){// *****}virtual void DrawShape(){// *****}virtual void WriteText(){// *****}virtual void Connect(){// *****}
}// Mobile平台实现
class MobileMessagerBase: public MessagerImpl{
public:virtual void PlaySound(){// *****}virtual void DrawShape(){// *****}virtual void WriteText(){// *****}virtual void Connect(){// *****}
}class MessagerLite: public Messager{ // 实现抽象类
private:MessagerImpl* messagerImpl; // 组合对象
public:MessagerLite(MessagerImpl *msgi): messagerImpl(msgi){}virtual void Login(){messager-Connect();// ******}virtual void SendMessage(){messager-WriteText();// ******}virtual void SendPicture(){messager-DrawShape();// ******}
};class MessagerPerfect: public Messager{ // 实现抽象类
private:MessagerImpl* messagerImpl; // 组合对象
public:MessagerPerfect(MessagerImpl *msgi): messagerImpl(msgi){}virtual void Login(){MobileMessagerBase::PlaySound();MobileMessagerBase::Connect();// ******}virtual void SendMessage(){MobileMessagerBase::PlaySound();MobileMessagerBase::WriteText();// ******}virtual void SendPicture(){MobileMessagerBase::PlaySound();MobileMessagerBase::DrawShape();// ******}
};这样就能完成所有的功能其核心点在于使用继承 组合的模式取代单一的继承方式来实现所有的功能采用桥模式的设计方式将类的膨胀改写成1 n m的形式整整比普通模式少了至少一个数量级的代码
4、总结
Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化即“子类化”它们。Bridge模式有时候类似于多继承方案但是多继承方案往往违背单一职责原则即一个类存在多个变化的原因和方向复用性比较差。Bridge模式是比多级车工方案更好的解决方案。Bridge模式的应用一般在“两个非常强的变化维度”有时一个类也可以有多余两个的变化维度这时可以使用Bridge的扩展模式。