设计模式之桥接模式

1 核心定义

桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们都可以独立地变化。通过使用组合关系代替继承关系,桥接模式可以减少子类的数量,并避免多层继承带来的复杂性

2 核心思想

分离抽象与实现:将抽象(接口)和实现(具体实现)解耦

组合优于继承:通过对象组合建立抽象和实现之间的关系

独立变化维度:抽象和实现可以独立扩展,互不影响

多维度变化:处理多个变化维度而不导致类爆炸

3 结构组成

Abstraction(抽象类):定义抽象接口,维护对实现对象的引用

RefinedAbstraction(扩充抽象类):扩展抽象类定义的接口

Implementor(实现者接口):定义实现类的接口

ConcreteImplementor(具体实现者):实现实现者接口的具体类

4 应用场景举例

以跨平台消息发送系统为例:

消息类型:普通消息、加急消息、特急消息

发送方式:邮件发送、短信发送、微信发送

需要支持不同消息类型与不同发送方式的任意组合

5 UML

6 c++ 实现

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 实现类接口:消息发送方式
class MessageSender {
public:
    virtual ~MessageSender() = default;
    virtual void send(const string& message, const string& recipient) = 0;
};

// 具体实现类:邮件发送
class EmailSender : public MessageSender {
public:
    void send(const string& message, const string& recipient) override {
        cout << "发送邮件给 [" << recipient << "]: " << message << endl;
        cout << "邮件发送成功!" << endl;
    }
};

// 具体实现类:短信发送
class SmsSender : public MessageSender {
public:
    void send(const string& message, const string& recipient) override {
        cout << "发送短信给 [" << recipient << "]: " << message << endl;
        cout << "短信发送成功!" << endl;
    }
};

// 具体实现类:微信发送
class WeChatSender : public MessageSender {
public:
    void send(const string& message, const string& recipient) override {
        cout << "发送微信给 [" << recipient << "]: " << message << endl;
        cout << "微信发送成功!" << endl;
    }
};

// 抽象类:消息类型
class Message {
protected:
    MessageSender* sender;  // 桥接到发送方式
    
public:
    Message(MessageSender* s) : sender(s) {}
    virtual ~Message() {
        delete sender;
    }
    
    virtual void sendMessage(const string& message, const string& recipient) = 0;
};

// 扩展抽象类:普通消息
class NormalMessage : public Message {
public:
    NormalMessage(MessageSender* s) : Message(s) {}
    
    void sendMessage(const string& message, const string& recipient) override {
        cout << "[普通消息] ";
        sender->send(message, recipient);
    }
};

// 扩展抽象类:加急消息
class UrgentMessage : public Message {
public:
    UrgentMessage(MessageSender* s) : Message(s) {}
    
    void sendMessage(const string& message, const string& recipient) override {
        cout << "[加急消息] 请立即处理!" << endl;
        sender->send("【加急】" + message, recipient);
    }
};

// 扩展抽象类:特急消息
class VeryUrgentMessage : public Message {
public:
    VeryUrgentMessage(MessageSender* s) : Message(s) {}
    
    void sendMessage(const string& message, const string& recipient) override {
        cout << "[特急消息] 火速处理!!!" << endl;
        cout << "系统将每隔5分钟提醒一次" << endl;
        sender->send("【特急】" + message, recipient);
    }
};

// 客户端代码
int main() {
    // 创建各种组合
    cout << "=== 测试用例1:普通邮件 ===" << endl;
    Message* m1 = new NormalMessage(new EmailSender());
    m1->sendMessage("Hello World", "user@example.com");
    cout << endl;
    
    cout << "=== 测试用例2:加急短信 ===" << endl;
    Message* m2 = new UrgentMessage(new SmsSender());
    m2->sendMessage("验证码:123456", "13800138000");
    cout << endl;
    
    cout << "=== 测试用例3:特急微信 ===" << endl;
    Message* m3 = new VeryUrgentMessage(new WeChatSender());
    m3->sendMessage("系统故障,请立即处理", "管理员");
    cout << endl;
    
    // 清理内存
    delete m1;
    delete m2;
    delete m3;
    
    return 0;
}

7 总结

不使用桥接模式的坏处

如果不使用桥接模式,通常会用继承的方式实现:

方式1:使用多层继承

cpp 复制代码
// 问题:类的数量爆炸
class Message { /* ... */ };
class EmailMessage : public Message { /* ... */ };
class SmsMessage : public Message { /* ... */ };
class WeChatMessage : public Message { /* ... */ };
class UrgentEmailMessage : public EmailMessage { /* ... */ };
class UrgentSmsMessage : public SmsMessage { /* ... */ };
class UrgentWeChatMessage : public WeChatMessage { /* ... */ };
class VeryUrgentEmailMessage : public UrgentEmailMessage { /* ... */ };
// ... 如果有3种消息类型和3种发送方式,就需要3*3=9个类

方式2:使用条件判断

cpp 复制代码
class Message {
private:
    string type;      // 消息类型
    string sendWay;   // 发送方式
    
public:
    void sendMessage(const string& msg, const string& recipient) {
        // 复杂的条件判断
        if (type == "normal" && sendWay == "email") {
            // 发送普通邮件
        } else if (type == "normal" && sendWay == "sms") {
            // 发送普通短信
        } else if (type == "urgent" && sendWay == "email") {
            // 发送加急邮件
        }
        // ... 需要为每种组合编写逻辑
    }
};

主要问题:

1 类爆炸:每增加一种消息类型或发送方式,类的数量会呈乘积增长

2 代码重复:不同类型的相同发送方式,会有大量重复代码

3 维护困难:修改某一发送方式的逻辑,需要修改所有相关子类

4 违反开闭原则:添加新的组合必须修改现有代码

5 静态绑定:组合关系在编译时就确定,无法在运行时改变

桥接模式的优势

1 分离抽象和实现:两个维度可以独立变化,互不影响

2 扩展性强:添加新的消息类型或发送方式都很简单

3 符合开闭原则:扩展时不需要修改现有代码

4 减少类数量:如果有M个抽象和N个实现,只需要M+N个类,而不是M*N个

5 运行时绑定:可以在运行时动态选择实现方式

8 适用场景

1 需要在抽象和实现之间增加更多的灵活性

2 一个类存在两个独立变化的维度

3 不希望使用继承导致类爆炸

4 需要在运行时切换不同的实现

桥接模式通过将继承关系改为组合关系,很好地解决了多维变化带来的复杂性问题,是设计模式中体现"优先使用对象组合而不是继承"原则的典型例子。

相关推荐
青春易逝丶2 小时前
桥接模式
桥接模式
Initialize-le2 小时前
WMware桥接模式配置静态IP上网
网络协议·tcp/ip·桥接模式
OxyTheCrack6 小时前
【C++】简述Observer观察者设计模式附样例(C++实现)
开发语言·c++·笔记·设计模式
愿天堂没有C++6 小时前
Pimpl 设计模式(指针指向实现)
开发语言·c++·设计模式
胖虎17 小时前
iOS中的设计模式(十二)- 迭代器模式(Iterator Pattern)在 iOS 开发中的实践
设计模式·迭代器模式
sanshizhang7 小时前
设计模式-责任链模式
java·设计模式·责任链模式
逆境不可逃7 小时前
【从零入门23种设计模式16】行为型之迭代器模式
java·开发语言·数据结构·算法·设计模式·职场和发展·迭代器模式
geovindu7 小时前
python: Singleton Pattern
开发语言·python·单例模式·设计模式
JTCC7 小时前
Java 设计模式西游篇 - 第七回:责任链模式过难关 通关文牒层层批
java·设计模式·责任链模式