23种设计模式23种设计模式
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
  • 结构型模式

    • 适配器模式 (Adapter)
    • 桥接模式 (Bridge)
    • 组合模式 (Composite)
    • 装饰器模式 (Decorator)
    • 外观模式 (Facade)
    • 享元模式 (Flyweight)
    • 代理模式 (Proxy)

桥接模式 (Bridge)

📖 通俗理解

想象你有一个遥控器和一台电视机:

  • 遥控器可以有不同种类:普通遥控器、高级遥控器
  • 电视机也可以有不同品牌:索尼、三星、小米

如果用继承来实现,你需要:

  • 索尼普通遥控器、索尼高级遥控器
  • 三星普通遥控器、三星高级遥控器
  • 小米普通遥控器、小米高级遥控器...

类的数量会爆炸式增长!

桥接模式的解决方案:把遥控器和电视机分开,用一座"桥"连接它们。遥控器持有电视机的引用,需要什么品牌的电视就传入什么品牌。

🎯 解决什么问题?

问题:当一个类存在两个或多个独立变化的维度时,使用继承会导致类爆炸。

例子:

  • 形状(圆形、方形)× 颜色(红色、蓝色)= 4个类
  • 形状(圆形、方形、三角形)× 颜色(红、蓝、绿)= 9个类
  • 随着维度增加,类的数量成倍增长!

解决:把这两个维度分离,用组合代替继承。

🌰 生活中的例子

  • 遥控器和电视:遥控器可以控制不同品牌的电视
  • 手机和充电器:不同手机可以用同一个充电器
  • 画笔和颜色:同一支笔可以蘸不同的颜料
  • 车和发动机:同一款车可以装不同品牌的发动机

💻 Java 代码实现

场景:不同形状 × 不同颜色

第一步:定义实现接口(颜色)

/**
 * 实现者接口:颜色
 */
public interface Color {
    String fill();
}

/**
 * 具体实现:红色
 */
public class RedColor implements Color {
    @Override
    public String fill() {
        return "红色";
    }
}

/**
 * 具体实现:蓝色
 */
public class BlueColor implements Color {
    @Override
    public String fill() {
        return "蓝色";
    }
}

/**
 * 具体实现:绿色
 */
public class GreenColor implements Color {
    @Override
    public String fill() {
        return "绿色";
    }
}

第二步:定义抽象类(形状)

/**
 * 抽象类:形状
 * 持有颜色的引用(这就是"桥")
 */
public abstract class Shape {
    
    // 桥接:持有实现者的引用
    protected Color color;
    
    public Shape(Color color) {
        this.color = color;
    }
    
    public abstract void draw();
}

/**
 * 扩展抽象:圆形
 */
public class Circle extends Shape {
    
    public Circle(Color color) {
        super(color);
    }
    
    @Override
    public void draw() {
        System.out.println("画一个" + color.fill() + "的圆形 ●");
    }
}

/**
 * 扩展抽象:正方形
 */
public class Square extends Shape {
    
    public Square(Color color) {
        super(color);
    }
    
    @Override
    public void draw() {
        System.out.println("画一个" + color.fill() + "的正方形 ■");
    }
}

/**
 * 扩展抽象:三角形
 */
public class Triangle extends Shape {
    
    public Triangle(Color color) {
        super(color);
    }
    
    @Override
    public void draw() {
        System.out.println("画一个" + color.fill() + "的三角形 ▲");
    }
}

第三步:使用桥接

public class Client {
    public static void main(String[] args) {
        // 红色圆形
        Shape redCircle = new Circle(new RedColor());
        redCircle.draw();
        
        // 蓝色正方形
        Shape blueSquare = new Square(new BlueColor());
        blueSquare.draw();
        
        // 绿色三角形
        Shape greenTriangle = new Triangle(new GreenColor());
        greenTriangle.draw();
        
        // 可以任意组合!
        System.out.println("--- 动态切换颜色 ---");
        Shape circle = new Circle(new BlueColor());
        circle.draw();  // 蓝色圆形
    }
}

输出:

画一个红色的圆形 ●
画一个蓝色的正方形 ■
画一个绿色的三角形 ▲
--- 动态切换颜色 ---
画一个蓝色的圆形 ●

🔥 实战案例:消息发送系统

不同类型的消息(普通、加急、特急)× 不同发送方式(短信、邮件、微信)

/**
 * 实现接口:消息发送方式
 */
public interface MessageSender {
    void send(String message, String to);
}

/**
 * 具体实现:短信发送
 */
public class SmsSender implements MessageSender {
    @Override
    public void send(String message, String to) {
        System.out.println("【短信】发送给 " + to + ": " + message);
    }
}

/**
 * 具体实现:邮件发送
 */
public class EmailSender implements MessageSender {
    @Override
    public void send(String message, String to) {
        System.out.println("【邮件】发送给 " + to + ": " + message);
    }
}

/**
 * 具体实现:微信发送
 */
public class WechatSender implements MessageSender {
    @Override
    public void send(String message, String to) {
        System.out.println("【微信】发送给 " + to + ": " + message);
    }
}

/**
 * 抽象类:消息
 */
public abstract class Message {
    
    // 桥接
    protected MessageSender sender;
    
    public Message(MessageSender sender) {
        this.sender = sender;
    }
    
    public abstract void sendMessage(String content, String to);
}

/**
 * 普通消息
 */
public class NormalMessage extends Message {
    
    public NormalMessage(MessageSender sender) {
        super(sender);
    }
    
    @Override
    public void sendMessage(String content, String to) {
        String message = "【普通】" + content;
        sender.send(message, to);
    }
}

/**
 * 加急消息
 */
public class UrgentMessage extends Message {
    
    public UrgentMessage(MessageSender sender) {
        super(sender);
    }
    
    @Override
    public void sendMessage(String content, String to) {
        String message = "【加急!】" + content;
        sender.send(message, to);
    }
}

/**
 * 特急消息
 */
public class VeryUrgentMessage extends Message {
    
    public VeryUrgentMessage(MessageSender sender) {
        super(sender);
    }
    
    @Override
    public void sendMessage(String content, String to) {
        String message = "【特急!!!】" + content + " 请立即处理!";
        // 特急消息:多渠道同时发送
        sender.send(message, to);
        System.out.println("  → 同时电话通知...");
    }
}

使用方式:

public class Client {
    public static void main(String[] args) {
        // 普通消息 + 短信
        Message msg1 = new NormalMessage(new SmsSender());
        msg1.sendMessage("下午3点开会", "张三");
        
        System.out.println();
        
        // 加急消息 + 邮件
        Message msg2 = new UrgentMessage(new EmailSender());
        msg2.sendMessage("项目明天上线,请准备", "开发团队");
        
        System.out.println();
        
        // 特急消息 + 微信
        Message msg3 = new VeryUrgentMessage(new WechatSender());
        msg3.sendMessage("生产环境故障", "运维团队");
    }
}

输出:

【短信】发送给 张三: 【普通】下午3点开会

【邮件】发送给 开发团队: 【加急!】项目明天上线,请准备

【微信】发送给 运维团队: 【特急!!!】生产环境故障 请立即处理!
  → 同时电话通知...

🔥 实战案例2:JDBC 驱动

JDBC 就是桥接模式的典型应用!

/**
 * 模拟 JDBC 的桥接结构
 */

// 实现接口:数据库驱动
public interface Driver {
    Connection connect(String url);
}

// MySQL 驱动
public class MySQLDriver implements Driver {
    @Override
    public Connection connect(String url) {
        System.out.println("使用 MySQL 驱动连接: " + url);
        return new MySQLConnection();
    }
}

// Oracle 驱动
public class OracleDriver implements Driver {
    @Override
    public Connection connect(String url) {
        System.out.println("使用 Oracle 驱动连接: " + url);
        return new OracleConnection();
    }
}

// 抽象类:DriverManager(桥)
public class DriverManager {
    
    private Driver driver;
    
    public void setDriver(Driver driver) {
        this.driver = driver;
    }
    
    public Connection getConnection(String url) {
        return driver.connect(url);
    }
}

📊 类图结构

        ┌─────────────────┐
        │   Abstraction   │ ──────────────┐
        │ + operation()   │               │
        └────────▲────────┘               │ 桥
                 │                        ▼
    ┌────────────┴────────────┐   ┌───────────────────┐
    │                         │   │    Implementor    │
┌───┴─────────┐  ┌────────────┴┐  │ + operationImpl() │
│RefinedAbst1 │  │RefinedAbst2 │  └─────────▲─────────┘
└─────────────┘  └─────────────┘            │
                                 ┌──────────┴──────────┐
                                 │                     │
                          ┌──────┴──────┐      ┌───────┴─────┐
                          │ConcreteImpl1│      │ConcreteImpl2│
                          └─────────────┘      └─────────────┘

⚠️ 桥接模式 vs 策略模式

很多人会搞混这两个模式,它们的区别是:

对比项桥接模式策略模式
目的解耦抽象和实现切换算法策略
关注点结构设计行为切换
变化维度两个维度都可变只有策略在变
使用场景设计阶段运行时切换算法

✅ 适用场景

  1. 多维度变化:一个类存在两个或多个独立变化的维度
  2. 避免继承爆炸:继承层次过深或子类过多
  3. 需要运行时切换实现:想在运行时动态改变实现

小结

桥接模式的核心:将抽象和实现分离,让它们可以独立变化。

关键:

  • 抽象部分持有实现部分的引用(桥)
  • 两个维度都可以独立扩展
  • 用组合代替继承,避免类爆炸

👉 下一篇:组合模式

Prev
适配器模式 (Adapter)
Next
组合模式 (Composite)