将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 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_10222 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
转世成为计算机大神5 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
小乖兽技术6 小时前
23种设计模式速记法
设计模式
小白不太白9507 小时前
设计模式之 外观模式
microsoft·设计模式·外观模式
小白不太白9507 小时前
设计模式之 原型模式
设计模式·原型模式
澄澈i7 小时前
设计模式学习[8]---原型模式
学习·设计模式·原型模式
小白不太白95014 小时前
设计模式之建造者模式
java·设计模式·建造者模式
菜菜-plus16 小时前
java 设计模式 模板方法模式
java·设计模式·模板方法模式
萨达大16 小时前
23种设计模式-模板方法(Template Method)设计模式
java·c++·设计模式·软考·模板方法模式·软件设计师·行为型设计模式