S5. 桥接模式

2021-12-06  本文已影响0人  开源519

桥接模式

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

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

场景

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

分析

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

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

桥接模式

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

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

将App抽象

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

APP抽象

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

将手机与APP分别抽象

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

APP和手机抽象

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

如此设计有以下优点:

代码

#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++设计模式 - 单例模式

上一篇 下一篇

猜你喜欢

热点阅读