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 需要在运行时切换不同的实现
桥接模式通过将继承关系改为组合关系,很好地解决了多维变化带来的复杂性问题,是设计模式中体现"优先使用对象组合而不是继承"原则的典型例子。