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

相关推荐
是2的10次方啊1 天前
设计模式与生活⑯:天冷了,出门这身得一层层配
设计模式
心若自由何处是束缚2 天前
适配器模式:从原理到实战的完整指南
设计模式·适配器模式
是2的10次方啊2 天前
设计模式与生活⑮:看到哪儿了,得有个地方替你记着
设计模式
2601_967979123 天前
设计模式 - 访问者模式
设计模式·访问者模式·应用场景·对象结构·操作分离
是2的10次方啊3 天前
设计模式与生活⑭:一栋楼,共用一份热
设计模式
是2的10次方啊4 天前
设计模式与生活⑬:你坐几号线,谁来运营是另一回事
设计模式
Tt有了t5 天前
设计模式速查
java·python·设计模式
一条Go5 天前
四个进程,一把锁:Alioth 的告警评测为什么不需要消息队列
后端·设计模式·架构
一缕82年的清风5 天前
被中产唾弃的“十元快剪”,藏着最狠的极客工程学
人工智能·设计模式
是2的10次方啊5 天前
设计模式与生活⑫:周报又到手,别从空白开始
设计模式