如何使用桥接模式进行代码重构?
业务场景
某系统需要向用户推送消息,有多种消息类型(普通、紧急、VIP)和多种推送渠道(短信、邮件、APP推送)。
原代码问题
继承爆炸
// 按类型×渠道组合,类数量爆炸
public class NormalSmsMessage extends Message { }
public class NormalEmailMessage extends Message { }
public class NormalAppMessage extends Message { }
public class UrgentSmsMessage extends Message { }
public class UrgentEmailMessage extends Message { }
public class UrgentAppMessage extends Message { }
public class VipSmsMessage extends Message { }
// ... 还有更多
类数量 = 消息类型数 × 渠道数 = M × N
新增一种消息类型需要增加N个类,新增一种渠道需要增加M个类。
桥接模式解决方案
模式定义
将抽象部分与实现部分分离,使它们可以独立变化。
核心思想
抽象层(消息类型)
│
│ 组合关系
↓
实现层(推送渠道)
类结构
Message(抽象消息)
│
├── send()
│
└── MessageSender sender ← 桥接
MessageSender(发送接口)
├── SmsSender
├── EmailSender
└── AppPushSender
重构后代码
实现层:推送渠道
// 发送接口
public interface MessageSender {
void send(String to, String content);
}
// 短信发送
@Component
public class SmsSender implements MessageSender {
@Override
public void send(String to, String content) {
smsClient.send(to, content);
}
}
// 邮件发送
@Component
public class EmailSender implements MessageSender {
@Override
public void send(String to, String content) {
emailClient.send(to, "通知", content);
}
}
// APP推送
@Component
public class AppPushSender implements MessageSender {
@Override
public void send(String to, String content) {
pushClient.push(to, content);
}
}
抽象层:消息类型
// 抽象消息
public abstract class Message {
protected MessageSender sender; // 桥接
public Message(MessageSender sender) {
this.sender = sender;
}
public abstract void send(String to, String content);
}
// 普通消息
public class NormalMessage extends Message {
public NormalMessage(MessageSender sender) {
super(sender);
}
@Override
public void send(String to, String content) {
sender.send(to, content);
}
}
// 紧急消息
public class UrgentMessage extends Message {
public UrgentMessage(MessageSender sender) {
super(sender);
}
@Override
public void send(String to, String content) {
// 紧急消息加前缀
sender.send(to, "【紧急】" + content);
// 紧急消息还要电话通知
phoneCall(to);
}
}
// VIP消息
public class VipMessage extends Message {
public VipMessage(MessageSender sender) {
super(sender);
}
@Override
public void send(String to, String content) {
// VIP专属格式
sender.send(to, "尊敬的VIP用户:" + content);
}
}
使用方式
@Service
public class NotificationService {
@Autowired
private SmsSender smsSender;
@Autowired
private EmailSender emailSender;
public void notifyUser(User user, String content, MessageType type) {
MessageSender sender = chooseSender(user);
Message message = createMessage(type, sender);
message.send(user.getContact(), content);
}
private Message createMessage(MessageType type, MessageSender sender) {
switch (type) {
case NORMAL: return new NormalMessage(sender);
case URGENT: return new UrgentMessage(sender);
case VIP: return new VipMessage(sender);
default: throw new IllegalArgumentException();
}
}
}
优化效果
类数量对比
| 维度 | 重构前 | 重构后 |
|---|---|---|
| 类数量 | M × N | M + N |
| 3类型×3渠道 | 9个类 | 6个类 |
| 5类型×5渠道 | 25个类 | 10个类 |
扩展性对比
| 操作 | 重构前 | 重构后 |
|---|---|---|
| 新增消息类型 | 增加N个类 | 增加1个类 |
| 新增渠道 | 增加M个类 | 增加1个类 |
桥接模式 vs 其他模式
| 模式 | 目的 | 关系 |
|---|---|---|
| 桥接模式 | 分离抽象与实现 | 组合 |
| 策略模式 | 算法可替换 | 组合 |
| 装饰器模式 | 动态添加职责 | 组合 |
| 适配器模式 | 接口转换 | 组合/继承 |
桥接模式的特点:两个维度都会变化,需要独立扩展。
面试答题框架
业务场景:消息推送,类型×渠道组合
原代码问题:
- 类数量爆炸(M×N)
- 扩展需修改多处
重构方案:桥接模式
- 抽象层:消息类型
- 实现层:推送渠道
- 通过组合关系桥接
效果:
- 类数量从M×N减为M+N
- 新增类型/渠道只需增加1个类
总结
| 要点 | 说明 |
|---|---|
| 适用场景 | 两个维度独立变化 |
| 核心思想 | 组合优于继承 |
| 关键实现 | 抽象层持有实现层引用 |
| 扩展性 | M×N → M+N |