美文网首页
S5. 桥接模式

S5. 桥接模式

作者: 开源519 | 来源:发表于2021-12-06 19:28 被阅读0次

桥接模式

桥接是一种结构型设计模式,可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。

简单的理解,就是将抽象部分与实现部分分离,实现解耦。

场景

实现Honor30Pro与Mate40手机的微信与王者荣耀APP。

分析

遇到此类场景时,通常我们会抽象出手机类,然后在不同的手机上实现客制化的APP(假设不同的手机品牌安装同一款APP会有一些参数差异)。

如果将手机抽象,可以得到如下类图:

桥接模式

如上设计是将各个品牌手机相同部分抽象出来,差异性的部分可在具体的子类中实现。因此也就能够实现具备王者荣耀和微信的不同品牌手机(Honor、Mate40)。

但是上述设计又暴露出如下问题:

  • 每增加一款手机,就要重新实现一个手机子类以及适应当前手机的各个APP。

  • 每个手机与其平台上的APP高度耦合。例如,当Hono30Pro类发生修改时,其子类王者荣耀APP以及微信APP都需要随之修改。

  • 这种设计还会导致APP与手机绑定,从而无法实现从某个手机卸载指定的APP。例:在Mate40手机卸载王者荣耀。

将App抽象

将APP抽象时,得到可用于Mate40与Honor30 Pro的微信与王者荣耀。

APP抽象

此种设计与第一种设计存在相同的问题。

将手机与APP分别抽象

当回头再分析场景时,发现场景存在两个实例,手机和APP,且为“has a”的关系,即聚合。那么可将手机与APP分别抽象,实现聚合的关系,子类无需关心两者间的关系。

APP和手机抽象

如上设计,仅CPhone类与CAPP类有耦合关系。在实际的实现中,CPhone与CAPP为依赖关系,具体CPhone子类与CAPP为依赖聚合关系。将原先高度耦合的关系,转换为CPhone子类与CAPP抽象类耦合。

如此设计有以下优点:

  • 完成CPhone子类与CApp子类的解耦。两者都可以独立修改,互不干扰。灵活性更强。
  • 更容易扩展。当需要增加新的手机或APP时,能够在不修改原有的代码基础上完成。

代码

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class CApp
{
public:
    CApp()
    {

    }

    virtual ~CApp()
    {

    }
    virtual string GetName() = 0;
    virtual void ShowLogo() = 0;
    virtual void RunPlatform(string platform) = 0;
};

class CHonorOfKings : public CApp
{
public:
    CHonorOfKings(string logo)
    {
        mLogo = logo;
        mName = "HonorOfKings";
    }

    ~CHonorOfKings()
    {

    }

    string GetName()
    {
        return mName;
    }

    void ShowLogo()
    {
        cout << mLogo << " (" << mPlatform << ")" << endl;
    }

    void RunPlatform(string platform)
    {
        mPlatform = platform;
    }

private:
    string mName;
    string mLogo;
    string mPlatform;
};

class CWeChat : public CApp
{
public:
    CWeChat(string logo)
    {
        mLogo = logo;
        mName = "WeChat";
    }

    ~CWeChat()
    {

    }

    string GetName()
    {
        return mName;
    }

    void ShowLogo()
    {
        cout << mLogo << " (" << mPlatform << ")" << endl;
    }

    void RunPlatform(string platform)
    {
        mPlatform = platform;
    }

private:
    string mName;
    string mLogo;
    string mPlatform;
};

class CPhone
{
public:
    virtual ~CPhone()
    {
    
    }

    virtual void InstallApp(CApp *pApp) = 0;

    virtual void Uninstall(CApp *pApp) = 0;

    virtual void EnterApp(CApp *pApp) = 0;

    virtual void ShowAppList() = 0;
};

class CMate40: public CPhone
{
public:
    explicit CMate40(string name)
    {
        mName = name;
    }

    ~CMate40()
    {

    }

    void InstallApp(CApp *pApp)
    {
        pApp->RunPlatform(mName);
        mAppVec.push_back(pApp);
    }

    void Uninstall(CApp *pApp)
    {
        vector<CApp *>::iterator it;

        for (it = mAppVec.begin(); it != mAppVec.end(); ) {
            if ((*it)->GetName() == pApp->GetName()) {
                cout << "Uninstall " << (*it)->GetName() << " Success!" << endl;
                /* void removing the last element, coredump */
                it = mAppVec.erase(it);
            } else {
                it++;
            }
        }
    }

    void EnterApp(CApp *pApp)
    {
        pApp->ShowLogo();
    }

    void ShowAppList()
    {
        vector<CApp *>::iterator it;

        cout << "App List: ";
        for (it = mAppVec.begin(); it != mAppVec.end(); ) {
            cout << (*it)->GetName() << " ";
            it++;
        }
        cout << endl;
    }

private:
    string mName;
    vector <CApp*> mAppVec;
};

class CHonor30Pro : public CPhone
{
public:
    explicit CHonor30Pro(string name)
    {
        mName = name;
    }

    ~CHonor30Pro()
    {

    }

    void InstallApp(CApp *pApp)
    {
        pApp->RunPlatform(mName);
        mAppVec.push_back(pApp);
    }

    void Uninstall(CApp *pApp)
    {
        vector<CApp *>::iterator it;

        for (it = mAppVec.begin(); it != mAppVec.end(); ) {
            if ((*it)->GetName() == pApp->GetName()) {
                cout << "Uninstall " << (*it)->GetName() << " Success!" << endl;
                /* void removing the last element, coredump */
                it = mAppVec.erase(it);
            } else {
                it++;
            }
        }
    }

    void EnterApp(CApp *pApp)
    {
        pApp->ShowLogo();
    }

    void ShowAppList()
    {
        vector<CApp *>::iterator it;

        cout << "App List: ";
        for (it = mAppVec.begin(); it != mAppVec.end(); ) {
            cout << (*it)->GetName() << " ";
            it++;
        }
        cout << endl;
    }

private:
    string mName;
    vector <CApp*> mAppVec;
};

int main(int argc, char *argv[])
{
    CHonorOfKings theHonorOfKings("Timi");
    CWeChat theWeChat("Earth");

    // 定制 Honor 30 Pro 上的王者荣耀和微信
    CHonor30Pro thePhone("Honor 30 Pro");

    cout << "--- Honor 30 Pro ---" << endl;
    thePhone.InstallApp(&theHonorOfKings);
    thePhone.EnterApp(&theHonorOfKings);

    thePhone.InstallApp(&theWeChat);
    thePhone.EnterApp(&theWeChat);

    thePhone.ShowAppList();

    thePhone.Uninstall(&theWeChat);
    thePhone.ShowAppList();
    cout << endl;

    // 定制 Mate40 上的王者荣耀和微信
    CMate40 theMate40("Mate40");

    cout << "--- Mate40 ---" << endl;
    theMate40.InstallApp(&theHonorOfKings);
    theMate40.EnterApp(&theHonorOfKings);

    theMate40.InstallApp(&theWeChat);
    theMate40.EnterApp(&theWeChat);

    theMate40.ShowAppList();

    theMate40.Uninstall(&theWeChat);
    theMate40.ShowAppList();
    cout << endl;

    return 0;
}

总结

  • 桥接模式主要将抽象与实现分离。完成相同的部分耦合,差异化部分解耦。使代码灵活性更强,达到类实现部分的修改不会影响到其他代码改动的效果。

  • 客户端代码仅能够与高层抽象部分交互,不会接触到具体实现的详细细节。

  • 履行开闭原则。新增抽象部分与实现部分,两者互不影响。

  • 履行单一原则。抽象部分专注于处理高层逻辑,实现部分处理差异化细节。

文章推荐

UML中类之间的关系

C++设计模式 - 单例模式

相关文章

  • S5. 桥接模式

    桥接模式 桥接是一种结构型设计模式,可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。 简单的理...

  • 设计模式-桥接模式

    设计模式-桥接模式 定义 桥接模式(Bridge Pattern)也称为桥梁模式、接口(Interface)模式或...

  • 结构型模式:桥接模式

    文章首发:结构型模式:桥接模式 七大结构型模式之二:桥接模式。 简介 姓名 :桥接模式 英文名 :Bridge P...

  • 设计模式之桥接模式

    设计模式之桥接模式 1. 模式定义 桥接模式又称柄体模式或接口模式,它是一种结构性模式。桥接模式将抽象部分与实现部...

  • 06-01-001 虚拟机的网络连接方式(转运整理)

    一、Bridged(桥接模式) 什么是桥接模式?桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥...

  • 桥接模式与中介模式

    桥接模式-BRIDGE 对桥接模式感兴趣,是因为公司业务上需要桥接Html5和ReactNative两个平台。桥接...

  • 设计模式——桥接模式

    设计模式——桥接模式 最近公司组件分享设计模式,然而分配给我的是桥接模式。就在这里记录我对桥接模式的理解吧。 定义...

  • 桥接模式

    个人博客http://www.milovetingting.cn 桥接模式 模式介绍 桥接模式也称为桥梁模式,是结...

  • 桥接模式

    桥接模式 参考原文: https://zhuanlan.zhihu.com/p/62390221 定义 桥接模式 ...

  • 10-桥接模式

    桥接模式-Bridge Pattern【学习难度:★★★☆☆,使用频率:★★★☆☆】 处理多维度变化——桥接模式(...

网友评论

      本文标题:S5. 桥接模式

      本文链接:https://www.haomeiwen.com/subject/whlnxrtx.html