将4年前的设计模式笔记再看一遍(5),Bridge

一、模式定义

子类急剧膨胀,需要重构,与Decorator一个分类。

将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立的变化。

1、最初设计

arduino 复制代码
class Messager {
public:
    virtual void login(string username, string password) = 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 PCMessagerBase: public Messager {
public:
    virtual void playSound() {
        // ...
    }
    
    virtual void drawShape() {
        // ...
    }
    virtual void writeText() {
        // ...
    }
    virtual void connect() {
        // ...
    }
};

class MobileMessagerBase: public Messager {
public:
    virtual void playSound() {
        // ...
    }
    
    virtual void drawShape() {
        // ...
    }
    virtual void writeText() {
        // ...
    }
    virtual void connect() {
        // ...
    }
};

// 业务抽象
class PCMessagerLite: public PCMessagerBase {
public:
    virtual void login(string username, string password) {
        PCMessagerBase::connect();
        // ...
    }
    
    virtual void sendMessage(string message) {
        PCMessagerBase::writeText();
        // ...
    }
    
    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::writeText();
        // ...
    }
    
    virtual void sendPicture(Image image) {
        PCMessagerBase::playSound();
        // ***
        PCMessagerBase::drawShape();
        // ...
    }
};

class MobileMessagerLite: public MobileMessagerBase {
public:
    virtual void login(string username, string password) {
        MobileMessagerBase::connect();
        // ...
    }
    
    virtual void sendMessage(string message) {
        MobileMessagerBase::writeText();
        // ...
    }
    
    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::writeText();
        // ...
    }
    
    virtual void sendPicture(Image image) {
        MobileMessagerBase::playSound();
        // ***
        MobileMessagerBase::drawShape();
        // ...
    }
};

// 使用
void process() {
    Messager* m = new MobileMessagerPerfect();
}

类的数目:1+n+m*n

2、优化方式

继承转组合。

csharp 复制代码
// 业务抽象

// MobileMessagerLite与PCMessagerLite合成一个类
class MessagerLite: public Messager {
    Messager* messager; // new MessagerBase();
public:
    virtual void login(string username, string password) {
        messager->connect();
        // ...
    }
    
    virtual void sendMessage(string message) {
        messager->writeText();
        // ...
    }
    
    virtual void sendPicture(Image image) {
        messager->drawShape();
        // ...
    }
};

// PCMessagerPerfect与MobileMessagerPerfect合二为一
class MessagerPerfect: public Messager {
    Messager* messager;
public:
    virtual void login(string username, string password) {
        messager->playSound();
        // ***
        messager->connect();
        // ...
    }
    
    virtual void sendMessage(string message) {
        messager->playSound();
        // ***
        messager->writeText();
        // ...
    }
    
    virtual void sendPicture(Image image) {
        messager->playSound();
        // ***
        messager->drawShape();
        // ...
    }
};

3、解决问题

上面两个类出现之后,是有问题的。因为Messager* messager;这一行,因为他俩要是具体指定为PCMessagerBase或者MobileMessagerBase的时候,会报错。因为PCMessagerBase是纯虚类,不能实例化的。要将Messager拆分为两个类。

同时,如果两个子类有相同字段,需要提取到基类中去。

类的个数变为1 + n + m,但是运行时候,还是有n*m种方式。

csharp 复制代码
class MessagerImp {
    virtual void playSound() = 0;
    virtual void drawShape() = 0;
    virtual void writeText() = 0;
    virtual void connect() = 0;
    
    virtual ~MessagerImp() {}
};

class Messager {
    MessagerImp* messagerImp; // new PCMessagerBase();
    
public:
    Messager(MessagerImp* imp): messagerImp(imp) {}

    virtual void login(string username, string password) = 0;
    virtual void sendMessage(string message) = 0;
    virtual void sendPicture(Image image) = 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:
    virtual void login(string username, string password) {
        messagerImp->connect();
        // ...
    }
    
    virtual void sendMessage(string message) {
        messagerImp->writeText();
        // ...
    }
    
    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->writeText();
        // ...
    }
    
    virtual void sendPicture(Image image) {
        messagerImp->playSound();
        // ***
        messagerImp->drawShape();
        // ...
    }
};

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

二、杂谈

1、整理之前看过一次,整理之时毫无印象。(4年后,此视频中对此模式的讲解,会跟C++语言有一些强关联性。抽象一些与语言无关的点是,如果发现相似的继承规则需要写两套时,就可以考虑是否可以将其中的某个继承提取为一个成员变量。)

2、继承自一个纯虚基类后,如果没有重写掉所有的纯虚函数,则这个继承后的子类,依然是一个纯虚基类。

3、桥模式和装饰器模式的区别是,装饰器模式可能会存在子类的组合,而桥模式简单些,是单链,不存在组合。

4、视频链接(4年后看自己的笔记,发现只是做了搬运,于是附上视频链接):www.youtube.com/watch?v=Qci...

5、另一个比较好的博客链接:refactoringguru.cn/design-patt...

相关推荐
Zane19949 小时前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..10 小时前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang15020 小时前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)1 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki2 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅662 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa2 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio
sarasuki2 天前
如何让 Agent 获取更多的能力?插件 / 技能系统
人工智能·设计模式·agent
sarasuki2 天前
如何让 Agent 安全运行你的命令 :命令分级 + Hook + 读写锁
人工智能·设计模式·agent
Zane19942 天前
技术不难,为什么项目却越改越不敢动?聊聊复杂系统开发该怎么想
设计模式