Bridge桥模式

博客探讨了在软件设计中遇到多维度变化的问题,如Messager类的功能和平台实现都可能变化。原始实现导致子类爆炸和大量重复代码。桥模式被提出作为一种解决方案,通过将抽象与实现分离,允许两者独立变化。重构过程中,将继承关系转换为组合,创建独立的抽象和实现类,并在运行时动态组装。这样提高了代码的灵活性和可维护性,避免了多继承带来的问题。
摘要由CSDN通过智能技术生成

1. 动机

  • 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。
  • 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?

下面以Messger类为例,其具有Login,SendMessage和SendPicture等多种功能。代码实现如下:

class Messager {
public:
    virtual void Login(string name, string passwd) = 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 PCMessagerImp : public Messager {
public:
    virtual void PlaySound()
    {
        //****
    }
    virtual void DrawShape()
    {
        //****
    }
    virtual void WriteText()
    {
        //****
    }
    virtual void Connect()
    {
        //****
    }
};

class MobileMessagerImp : public Messager {
public:
    virtual void PlaySound()
    {
        //****
    }
    virtual void DrawShape()
    {
        //****
    }
    virtual void WriteText()
    {
        //****
    }
    virtual void Connect()
    {
        //****
    }
};
// 业务抽象
class PCMessagerLite : public PCMessagerImp {
public:
    virtual void Login(string name, string passwd)
    {
        PCMessagerImp::Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        PCMessagerImp::WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        PCMessagerImp::DrawShape();
        // ....
    }
};

class MobileMessagerLite : public MobileMessagerImp {
public:
    virtual void Login(string name, string passwd)
    {
        MobileMessagerImp::Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        MobileMessagerImp::WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        MobileMessagerImp::DrawShape();
        // ....
    }
};

class PCMessagerPrefect : public PCMessagerImp {
public:
    virtual void Login(string name, string passwd)
    {
        PCMessagerImp::PlaySound();
        PCMessagerImp::Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        PCMessagerImp::PlaySound();
        PCMessagerImp::WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        PCMessagerImp::PlaySound();
        PCMessagerImp::DrawShape();
        // ....
    }
};

class MobileMessagerPrefect : public MobileMessagerImp {
public:
    virtual void Login(string name, string passwd)
    {
        MobileMessagerImp::PlaySound();
        MobileMessagerImp::Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        MobileMessagerImp::PlaySound();
        MobileMessagerImp::WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        MobileMessagerImp::PlaySound();
        MobileMessagerImp::DrawShape();
        // ....
    }
};

继承关系如下:
在这里插入图片描述
上述demo存在的问题:
1)随着功能扩展,子类急剧增加;
2)子类之间存在大量重复。

2. 桥模式定义

将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。 ——《设计模式》GoF

3. 桥模式结构图

在这里插入图片描述

4. 桥模式实现

使用桥模式进行重构

  • step1:继承变组合,使用组合的方式引出多态使用
  • step2:添加继承,遵循Messager 的结构
class Messager {
public:
    virtual void Login(string name, string passwd) = 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 PCMessagerImp : public Messager {
public:
    virtual void PlaySound()
    {
        //****
    }
    virtual void DrawShape()
    {
        //****
    }
    virtual void WriteText()
    {
        //****
    }
    virtual void Connect()
    {
        //****
    }
};

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

class MessagerLite : public Messager {
    Messager *messager;
public:
    virtual void Login(string name, string passwd)
    {
        messager->Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        messager->WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        messager->DrawShape();
        // ....
    }
};

class MessagerPrefect : public Messager {
    Messager *messager;
public:
    virtual void Login(string name, string passwd)
    {
        messager->PlaySound();
        messager->Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        messager->PlaySound();
        messager->WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        messager->PlaySound();
        messager->DrawShape();
        // ....
    }
};
  • step3:抽象部分和实现部分分离
class Messager {
protected:
    MessagerImp *messagerImp;
public:
    Messager(MessagerImp *msgImp) : messagerImp(msgImp)
    {}
    virtual void Login(string name, string passwd) = 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 ~Messager(){}
};

// 平台实现
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()
    {
        //****
    }
};

class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp *msgImp) : Messager(msgImp)
    {}
    virtual void Login(string name, string passwd)
    {
        messagerImp->Connect();
        // ....
    }
    virtual void SendMessage(string message)
    {
        messagerImp->WriteText();
        // ....
    }
    virtual void SendPicture(Image image)
    {
        messagerImp->DrawShape();
        // ....
    }
};

class MessagerPrefect : public Messager {
public:
    MessagerPrefect(MessagerImp *msgImp) : Messager(msgImp)
    {}
    virtual void Login(string name, string passwd)
    {
        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 *msgImp = new PCMessagerImp();
    Messager *m = new MessagerLite (msgImp);
}

在这里插入图片描述

5. 总结要点

  • Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。
  • Bridge模式有时候类似于多继承方案,但是多继承方案往往违背 单一职责原则(即一个类只有一个变化的原因),复用性比较差。 Bridge模式是比多继承方案更好的解决方法。
  • Bridge模式的应用一般在“两个非常强的变化维度”,有时一个 类也有多于两个的变化维度,这时可以使用Bridge的扩展模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值