C++ 设计模式 桥模式

以下内容均来自GeekBand极客班C++ 设计模式课程(李建忠老师主讲)

完整代码见:https://download.csdn.net/download/qq_41605114/18881737

Bridge

“单一职责”模式:

在软件组件的设计中,如果责任划分不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码(典型的Bad smell),这时候的关键是划分责任。

典型模式:

Decorator

Bridge

动机(Motivation)

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

现在有如下示例,一个多平台的消息系统

 

示例

class Messager

class Messager{
public:
    virtual void Login(string username,string password) = 0;
    virtual void sendMessage(string message) = 0;
    virtual void SendPicture(Image iamge) = 0;

    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~Messager(){}
};

提高信息传递的功能

下面有两个平台进行实现,一个PC,一个移动端Mobile

class PC

//平台实现
class PCMessagerBase : public Messager{
public:
    virtual void PlaySound(){
       //**********
    }
    virtual void DrawShape(){
       //**********
    }
    virtual void WirteText(){
       //**********
    }
    virtual void Connect(){
        //*********
    }
};

对于PC平台,还有两个对应的版本

//业务抽象
//经典版本
class PCMessagerLite : public PCMessagerBase{
public:
    virtual void Login(string username,string password){
        PCMessagerBase::Connect();
        //....
    }
    virtual void sendMessage(string message){
        PCMessagerBase::WirteText();
        //....
    }
    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::WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        PCMessagerBase::PlaySound();
        PCMessagerBase::DrawShape();
        //....
    }
};

 

 class Mobile

class MobileMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        //+++++++
    }
    virtual void DrawShape(){
        //+++++++
    }
    virtual void WriteText(){
        //+++++++
    }
    virtual void Connect(){
        //+++++++
    }
};

对于Mobile平台,还有两个对应的版本

//经典版本
class MobileMessagerLite : public MobileMessagerBase{
public:
    virtual void Login(string username,string password){
        MobileMessagerBase::Connect();
        //....
    }
    virtual void sendMessage(string message){
        MobileMessagerBase::WirteText();
        //....
    }
    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::WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        MobileMessagerBase::PlaySound();
        MobileMessagerBase::DrawShape();
        //....
    }
};

我们观察两个类中的两个函数:

//PC侧的完美版本
class PCMessagerPerfect : public PCMessagerBase{
public:
    virtual void Login(string username,string password){
        PCMessagerBase::PlaySound();
        PCMessagerBase::Connect();
        //....
    }
};
//Mobile完美版本
class MobileMessagerPerfect : public MobileMessagerBase{
public:
    virtual void Login(string username,string password){
        MobileMessagerBase::PlaySound();
        MobileMessagerBase::Connect();
        //....
    }
};

高度重复,调用的全是相同的虚函数,完全可以进行重构

我们先将PC端中,继承全部改掉:

//业务抽象
//经典版本
class PCMessagerLite{
    PCMessagerBase * messager;
public:
    virtual void Login(string username,string password){
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //....
    }
};
//完美版本
class PCMessagerPerfect{
    PCMessagerBase * messager;
public:
    virtual void Login(string username,string password){
        messager->PlaySound();
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->PlaySound();
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->PlaySound();
        messager->DrawShape();
        //....
    }
};

Mobile端同理

//经典版本
class MobileMessagerLite{
    MobileMessagerBase * messager;
public:
    virtual void Login(string username,string password){
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //....
    }
};
//完美版本
class MobileMessagerPerfect{
    MobileMessagerBase * messager;
public:
    virtual void Login(string username,string password){
        messager->PlaySound();
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->PlaySound();
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->PlaySound();
        messager->DrawShape();
        //....
    }
};

之后我们就发现,完全可以将这两个字段提取到同一个抽象父类中,恰巧我们现在有MessagerLite

//业务抽象
//经典版本
class MessagerLite{
    Messager * messager;
public:
    virtual void Login(string username,string password){
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //....
    }
};
//完美版本
class MessagerPerfect{
    Messager * messager;
public:
    virtual void Login(string username,string password){
        messager->PlaySound();
        messager->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messager->PlaySound();
        messager->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messager->PlaySound();
        messager->DrawShape();
        //....
    }
};

但是现在有一个问题,Class PCMessagerBase和Class MobileMessagerBase,都还是纯虚函数,因为并没有全部重写Messager类中的全部虚函数

Class MessagerPerfect和MessagerLite类中,又是重写了Messager类中的部分虚函数,显然,Messager的责任冗余且不清晰

所以现在要对Messager进行切割

class Messager{
protected:
    MessagerImp * messagerImp;
public:
    Messager(MessagerImp * arg):messagerImp(arg){
        
    }
    virtual void Login(string username,string password) = 0;
    virtual void sendMessage(string message) = 0;
    virtual void SendPicture(Image iamge) = 0;

    virtual ~Messager(){}
};
class MessagerImp{
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~MessagerImp(){}
};

之后再对部分内容进行修改

//平台实现
class PCMessagerBase : public MessagerImp{
public:
    virtual void PlaySound(){
       //**********
    }
    virtual void DrawShape(){
       //**********
    }
    virtual void WirteText(){
       //**********
    }
    virtual void Connect(){
        //*********
    }
};

class MobileMessagerBase : public MessagerImp{
public:
    virtual void PlaySound(){
        //+++++++
    }
    virtual void DrawShape(){
        //+++++++
    }
    virtual void WriteText(){
        //+++++++
    }
    virtual void Connect(){
        //+++++++
    }
};

//业务抽象
//经典版本
class MessagerLite : public Messager{
public:
    virtual void Login(string username,string password){
        messagerImp->Connect();
        //....
    }
    virtual void sendMessage(string message){
        messagerImp->WirteText();
        //....
    }
    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->WirteText();
        //....
    }
    virtual void SendPicture(Image image){
        messagerImp->PlaySound();
        messagerImp->DrawShape();
        //....
    }
};

具体调用:

void Process(){
    // 运行时装配
    MessagerImp * mImp = new PCMessagerBase();
    Messager * m = new Messager(mImp);
};

要点总结:

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值