将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...

相关推荐
jump_jump1 小时前
GetX — Flutter 的瑞士军刀,还是过度封装的陷阱?
flutter·设计模式·前端框架
wuyikeer7 小时前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
Old Uncle Tom11 小时前
Agent 技能的五种设计模式
设计模式
祁_z12 小时前
【ReACT 设计模式】(思考 - 行动 - 观察)
设计模式
Makoto_Kimur13 小时前
Spring用了哪些设计模式?
java·spring·设计模式
sg_knight14 小时前
设计模式实战:中介者模式(Mediator)
microsoft·设计模式·中介者模式
geovindu14 小时前
go: Prototype Pattern
开发语言·设计模式·golang·原型模式
我爱cope15 小时前
【从0开始学设计模式-11| 外观模式】
microsoft·设计模式·外观模式
两年半的个人练习生^_^15 小时前
每日一学:设计模式之代理模式
java·设计模式·代理模式
无籽西瓜a15 小时前
【西瓜带你学设计模式 | 第十九期 - 状态模式】状态模式 —— 状态流转与行为切换实现、优缺点与适用场景
java·后端·设计模式·状态模式·软件工程