桥接模式 (Bridge Pattern)
将抽象部分与它的实现部分分离,使它们都可以独立地变化
模式定义
桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。桥接模式用组合关系代替继承关系,降低了抽象和实现这两个可变维度的耦合度。
模式结构
graph TD
A[Client] --> B((Abstraction))
B --> C[RefinedAbstraction]
B --> D[Implementor]
D --> E[ConcreteImplementor]
实现方式
基础实现
定义抽象部分和实现部分的接口,通过组合关系连接它们。
// 实现部分接口
public interface DrawAPI {
void drawCircle(int radius, int x, int y);
}
// 具体实现A
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", y: " + y + "]");
}
}
// 具体实现B
public class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", y: " + y + "]");
}
}
// 抽象部分
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
// 细化抽象
public class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
drawAPI.drawCircle(radius, x, y);
}
}
使用示例
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100, 100, 10, new RedCircle());
Shape greenCircle = new Circle(100, 100, 10, new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}
复杂示例
更复杂的桥接模式示例,展示多维度变化。
// 消息发送接口 - 实现部分
public interface MessageSender {
void sendMessage(String message);
}
// 邮件发送实现
public class EmailSender implements MessageSender {
@Override
public void sendMessage(String message) {
System.out.println("通过邮件发送: " + message);
}
}
// 短信发送实现
public class SmsSender implements MessageSender {
@Override
public void sendMessage(String message) {
System.out.println("通过短信发送: " + message);
}
}
// 微信发送实现
public class WeChatSender implements MessageSender {
@Override
public void sendMessage(String message) {
System.out.println("通过微信发送: " + message);
}
}
// 消息抽象类
public abstract class Message {
protected MessageSender messageSender;
public Message(MessageSender messageSender) {
this.messageSender = messageSender;
}
public abstract void send(String message);
}
// 普通消息
public class NormalMessage extends Message {
public NormalMessage(MessageSender messageSender) {
super(messageSender);
}
@Override
public void send(String message) {
messageSender.sendMessage("普通消息: " + message);
}
}
// 加急消息
public class UrgentMessage extends Message {
public UrgentMessage(MessageSender messageSender) {
super(messageSender);
}
@Override
public void send(String message) {
messageSender.sendMessage("加急消息: " + message);
}
}
// 客户端使用
public class MessageClient {
public static void main(String[] args) {
// 发送普通邮件
Message normalEmail = new NormalMessage(new EmailSender());
normalEmail.send("Hello World");
// 发送加急短信
Message urgentSms = new UrgentMessage(new SmsSender());
urgentSms.send("紧急通知");
// 发送普通微信消息
Message normalWeChat = new NormalMessage(new WeChatSender());
normalWeChat.send("你好");
}
}
经典案例
JDBC驱动
JDBC是桥接模式的经典应用,将数据库访问抽象与具体数据库实现分离。
// JDBC桥接模式示例
import java.sql.*;
public class JdbcBridgeExample {
public static void main(String[] args) {
try {
// 加载MySQL驱动 - 具体实现
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立连接 - 抽象部分
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test", "user", "password");
// 创建Statement - 抽象部分
Statement stmt = conn.createStatement();
// 执行查询 - 抽象部分
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 处理结果
while (rs.next()) {
System.out.println("User: " + rs.getString("name"));
}
// 关闭资源
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// DriverManager是抽象部分
// 各种数据库驱动是实现部分
// 通过桥接模式,可以使用统一的接口访问不同的数据库
跨平台UI框架
UI框架中将界面元素抽象与平台实现分离。
// UI渲染接口 - 实现部分
public interface UIRenderer {
void renderButton(String text);
void renderTextBox(String text);
void renderWindow(String title);
}
// Windows平台实现
public class WindowsRenderer implements UIRenderer {
@Override
public void renderButton(String text) {
System.out.println("Windows风格按钮: " + text);
}
@Override
public void renderTextBox(String text) {
System.out.println("Windows风格文本框: " + text);
}
@Override
public void renderWindow(String title) {
System.out.println("Windows风格窗口: " + title);
}
}
// Mac平台实现
public class MacRenderer implements UIRenderer {
@Override
public void renderButton(String text) {
System.out.println("Mac风格按钮: " + text);
}
@Override
public void renderTextBox(String text) {
System.out.println("Mac风格文本框: " + text);
}
@Override
public void renderWindow(String title) {
System.out.println("Mac风格窗口: " + title);
}
}
// UI元素抽象
public abstract class UIElement {
protected UIRenderer renderer;
public UIElement(UIRenderer renderer) {
this.renderer = renderer;
}
public abstract void render();
}
// 按钮元素
public class Button extends UIElement {
private String text;
public Button(UIRenderer renderer, String text) {
super(renderer);
this.text = text;
}
@Override
public void render() {
renderer.renderButton(text);
}
}
// 窗口元素
public class Window extends UIElement {
private String title;
public Window(UIRenderer renderer, String title) {
super(renderer);
this.title = title;
}
@Override
public void render() {
renderer.renderWindow(title);
}
}
// 客户端使用
public class UIBridgeClient {
public static void main(String[] args) {
// Windows平台UI
UIRenderer windowsRenderer = new WindowsRenderer();
UIElement winButton = new Button(windowsRenderer, "确定");
UIElement winWindow = new Window(windowsRenderer, "主窗口");
winButton.render();
winWindow.render();
System.out.println("---");
// Mac平台UI
UIRenderer macRenderer = new MacRenderer();
UIElement macButton = new Button(macRenderer, "确定");
UIElement macWindow = new Window(macRenderer, "主窗口");
macButton.render();
macWindow.render();
}
}
适用场景
- 不希望在抽象和实现之间形成固定的绑定关系
- 抽象和实现部分都可以通过子类来扩展
- 想在多个对象间共享实现部分
- 当抽象和实现需要独立变化时,桥接模式可以将它们解耦,使它们可以独立地扩展
- 当需要对抽象部分和实现部分进行扩展时,桥接模式可以方便地增加新的具体类
- 当实现部分需要被多个抽象部分共享时,桥接模式可以避免代码重复
优缺点
优点
- 分离抽象和实现:桥接模式将抽象部分和实现部分分离,提高了系统的可扩展性
- 提高可扩展性:抽象和实现可以独立扩展,符合开闭原则
- 隐藏实现细节:客户端不需要知道实现的细节,只需要关注抽象接口
- 符合开闭原则:抽象和实现可以独立进行扩展
- 实现细节对客户透明:客户可以透明地使用不同的实现
缺点
- 增加系统复杂度:桥接模式会增加系统的理解难度,需要识别出系统中两个独立变化的维度
- 要求正确识别维度:需要正确识别出系统中两个独立变化的维度,这需要丰富的设计经验
- 可能不符合里氏替换原则:在某些情况下,桥接模式的实现可能不符合里氏替换原则
- 需要识别出两个独立变化的维度:设计阶段需要准确识别系统中的抽象和实现