网站Logo Ilren 小记

Java设计模式-桥接模式

jack
5
2023-05-05

🌉 桥接模式(Bridge Pattern):解耦抽象与实现的优雅之桥

模式简介
桥接模式是一种结构型设计模式,它将抽象部分与其实现部分分离,使它们可以独立变化。就像连接两岸的桥梁——桥的样式和建筑材料可以独立演进,而不互相影响。

📦 应用场景

  • GUI开发中跨平台渲染(如不同OS的窗口绘制)

  • 支付系统中支付方式与支付渠道的组合

  • 设备遥控器抽象与具体设备的解耦

  • JDBC驱动架构

  • 消息系统中消息类型与发送方式的组合

🧠 核心实现思路

  1. Abstraction(抽象部分):定义高层控制逻辑

  2. Implementation(实现部分):定义底层具体实现接口

  3. RefinedAbstraction(扩展抽象):扩展后的业务控制逻辑

  4. ConcreteImplementation(具体实现):实现接口的具体类

🧱 桥接模式的实现方式

1. 经典实现(遥控器与设备示例)

// 实现部分接口(设备)
interface Device {
    void enable();
    void disable();
    void setVolume(int percent);
    int getVolume();
}

// 具体实现(电视)
class Tv implements Device {
    private boolean on = false;
    private int volume = 30;
    
    public void enable() { on = true; }
    public void disable() { on = false; }
    public void setVolume(int percent) {
        volume = Math.min(100, Math.max(0, percent));
    }
    public int getVolume() { return volume; }
}

// 抽象部分(遥控器)
abstract class Remote {
    protected Device device;
    
    public Remote(Device device) {
        this.device = device;
    }
    
    abstract void power();
    abstract void volumeUp();
    abstract void volumeDown();
}

// 扩展抽象(高级遥控器)
class AdvancedRemote extends Remote {
    public AdvancedRemote(Device device) {
        super(device);
    }
    
    void power() {
        if (device.getVolume() > 0) {
            device.disable();
        } else {
            device.enable();
        }
    }
    
    void volumeUp() {
        device.setVolume(device.getVolume() + 10);
    }
    
    void volumeDown() {
        device.setVolume(device.getVolume() - 10);
    }
    
    void mute() {  // 新增功能
        device.setVolume(0);
    }
}

// 使用
Device tv = new Tv();
Remote remote = new AdvancedRemote(tv);
remote.volumeUp();

2. 支付系统实战(支付方式+支付渠道)

// 实现部分接口(支付渠道)
interface PaymentGateway {
    void processPayment(double amount);
}

// 具体实现(支付宝渠道)
class AlipayGateway implements PaymentGateway {
    public void processPayment(double amount) {
        System.out.println("支付宝支付:" + amount + "元");
    }
}

// 抽象部分(支付方式)
abstract class Payment {
    protected PaymentGateway gateway;
    
    public Payment(PaymentGateway gateway) {
        this.gateway = gateway;
    }
    
    abstract void makePayment(double amount);
}

// 扩展抽象(信用卡支付)
class CreditCardPayment extends Payment {
    private String cardNumber;
    
    public CreditCardPayment(PaymentGateway gateway, String cardNumber) {
        super(gateway);
        this.cardNumber = cardNumber;
    }
    
    void makePayment(double amount) {
        System.out.println("信用卡" + cardNumber.substring(12) + "支付中...");
        gateway.processPayment(amount);
    }
}

// 使用
PaymentGateway alipay = new AlipayGateway();
Payment payment = new CreditCardPayment(alipay, "6225880123456789");
payment.makePayment(999.99);

3. JDBC中的桥接模式

// JDBC架构中的桥接模式体现:
// Abstraction: Connection/Statement
// Implementation: Driver
Connection conn = DriverManager.getConnection(url); // 获取具体实现的桥接

💎 最佳实践推荐

动态组合实现

// 使用Map维护多种实现组合
class PaymentSystem {
    private Map<String, PaymentGateway> gateways = Map.of(
        "alipay", new AlipayGateway(),
        "wechat", new WechatPayGateway()
    );
    
    public Payment createPayment(String type, String account) {
        return new CreditCardPayment(gateways.get(type), account);
    }
}

Spring中的桥接应用

@Configuration
public class BridgeConfig {
    @Bean 
    public PaymentGateway alipayGateway() {
        return new AlipayGateway();
    }
    
    @Bean
    public Payment creditCardPayment(PaymentGateway gateway) {
        return new CreditCardPayment(gateway, "default-card");
    }
}

💣 常见问题与解决方案

问题1:桥接模式 vs 适配器模式?

区别

  • 适配器:事后补救,让不兼容的接口协同工作

  • 桥接:事前设计,让抽象和实现独立变化

问题2:如何避免实现类膨胀?

解决方案

  • 使用工厂方法创建具体实现

  • 结合策略模式动态选择实现

问题3:何时选择桥接模式?

决策树

需要多维度变化吗?
├─ 是 → 考虑桥接模式
└─ 否 → 可能过度设计

📊 模式对比

模式

关注点

灵活性

复杂度

桥接模式

抽象/实现解耦

⭐⭐⭐

⭐⭐

策略模式

算法替换

⭐⭐

抽象工厂

产品族创建

⭐⭐

⭐⭐⭐

📚 实际应用案例

  1. 跨平台UI开发

    // 抽象:Window
    // 实现:WindowsUI/LinuxUI/MacUI
    Window window = new DialogWindow(new MacUI());
  2. 消息系统

    // 抽象:Message
    // 实现:EmailSender/SmsSender/WechatSender
    Message msg = new UrgentMessage(new SmsSender());
    msg.send("Alert!");
  3. 游戏开发

    // 抽象:Character
    // 实现:DirectXRenderer/OpenGLRenderer
    Character hero = new Warrior(new OpenGLRenderer());
    hero.draw();

🎯 总结建议

  1. 识别变化维度:至少两个独立变化方向时才适用

  2. 避免过度设计:简单场景直接用继承

  3. 结合其他模式:常与抽象工厂、策略模式配合使用

  4. 接口设计:实现接口要保持足够抽象

  5. Spring集成:利用DI容器管理实现部分

动物装饰