模式定义

桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。桥接模式用组合关系代替继承关系,降低了抽象和实现这两个可变维度的耦合度。

模式结构

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();
    }
}

适用场景

优缺点

优点

  • 分离抽象和实现:桥接模式将抽象部分和实现部分分离,提高了系统的可扩展性
  • 提高可扩展性:抽象和实现可以独立扩展,符合开闭原则
  • 隐藏实现细节:客户端不需要知道实现的细节,只需要关注抽象接口
  • 符合开闭原则:抽象和实现可以独立进行扩展
  • 实现细节对客户透明:客户可以透明地使用不同的实现

缺点

  • 增加系统复杂度:桥接模式会增加系统的理解难度,需要识别出系统中两个独立变化的维度
  • 要求正确识别维度:需要正确识别出系统中两个独立变化的维度,这需要丰富的设计经验
  • 可能不符合里氏替换原则:在某些情况下,桥接模式的实现可能不符合里氏替换原则
  • 需要识别出两个独立变化的维度:设计阶段需要准确识别系统中的抽象和实现