在软件开发中,我们经常遇到多维度变化的需求,如果不合理地设计代码结构,随着需求的扩展,代码会变得越来越复杂,难以维护。桥接模式(Bridge Pattern) 就是一种强大的结构型设计模式,能够有效地解耦代码中的抽象部分(Abstraction) 和 实现部分(Implementation),让它们可以独立变化,提高代码的扩展性和灵活性。
在本文中,我们将从实际问题出发,探讨如何通过桥接模式优化代码结构,并结合 JDK 和 Spring 框架 的应用场景,帮助你更好地理解和掌握这一模式。
假设我们正在开发一款跨平台的消息发送系统,支持以下功能:
一个直接的设计方式是创建不同的类来表示各种组合,比如:
class SmsCommonMessage { }
class SmsUrgentMessage { }
class SmsVeryUrgentMessage { }
class EmailCommonMessage { }
class EmailUrgentMessage { }
class EmailVeryUrgentMessage { }
class AppCommonMessage { }
class AppUrgentMessage { }
class AppVeryUrgentMessage { }
这样一来,随着消息类别和发送渠道的增加,我们需要创建的类数会呈现指数级增长,代码变得臃肿且难以维护。
桥接模式(Bridge Pattern) 主要用于将抽象部分与实现部分分离,使它们可以独立地变化,从而减少代码的复杂度。
┌────────────────┐
│ Abstraction │
├────────────────┤
│ sendMessage() │
└────────────────┘
│
▼
┌──────────────────┐
│ RefinedAbstraction │
├──────────────────┤
│ sendMessage() │
└──────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Implementor │ │ ConcreteImplementor │
├────────────────┤ ├────────────────┤
│ send() │ │ send() │
└────────────────┘ └────────────────┘
我们将 消息类别 作为抽象部分,消息发送渠道 作为实现部分,并通过组合来建立它们之间的桥梁。
// 定义消息发送接口
interface MessageSender {
void send(String message);
}
// 短信发送实现
class SmsSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("发送短信: " + message);
}
}
// 邮件发送实现
class EmailSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("发送邮件: " + message);
}
}
// 应用内通知实现
class AppNotificationSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("发送应用通知: " + message);
}
}
// 抽象消息类
abstract class Message {
protected MessageSender sender;
public Message(MessageSender sender) {
this.sender = sender;
}
abstract void sendMessage(String message);
}
// 普通消息
class CommonMessage extends Message {
public CommonMessage(MessageSender sender) {
super(sender);
}
@Override
void sendMessage(String message) {
System.out.print("[普通消息] ");
sender.send(message);
}
}
// 加急消息
class UrgentMessage extends Message {
public UrgentMessage(MessageSender sender) {
super(sender);
}
@Override
void sendMessage(String message) {
System.out.print("[加急消息] ");
sender.send(message);
}
}
public class BridgePatternTest {
public static void main(String[] args) {
// 发送普通消息(短信)
Message message1 = new CommonMessage(new SmsSender());
message1.sendMessage("请假申请");
// 发送加急消息(邮件)
Message message2 = new UrgentMessage(new EmailSender());
message2.sendMessage("服务器宕机警报!");
}
}
[普通消息] 发送短信: 请假申请
[加急消息] 发送邮件: 服务器宕机警报!
Java 的 Abstract Window Toolkit(AWT) 使用桥接模式来处理不同操作系统上的 GUI 显示:
java.awt.Button
(抽象部分)java.awt.peer.ButtonPeer
(实现部分)这样,Java AWT 可以在不同操作系统(Windows、Mac、Linux)上无缝运行,而无需修改代码。
Spring 的 JDBC 访问策略 也是桥接模式的应用:
JdbcTemplate
DriverManagerDataSource
、HikariDataSource
)JdbcTemplate jdbcTemplate = new JdbcTemplate(new HikariDataSource());
这样,Spring 不依赖具体数据库,可以轻松切换不同的数据库驱动(MySQL、PostgreSQL、Oracle等)。
你是否在项目中遇到类似的扩展问题?尝试使用桥接模式优化你的代码吧!