「手写设计模式」桥接模式

141 阅读1分钟

理解名称

桥接模式(Bridge Design Pattern)在GoF《设计模式》中的定义如下:

Decouple an abstraction from its implementation so that the two can vary independently。将抽象和实现解耦,让它们可以独立变化。

这个模式主要强调了两个思想:

  • 面向接口编程
  • 组合优于继承

作用

解耦抽象实现,让它们可以独立变化。通过组合关系来替代继承关系,避免继承层次的指数级爆炸。

适用场景

  • 程序经常需要应对变化
  • 提高程序可扩展性
  • 避免继承层次的指数级爆炸

代码示例

以JDBC为例

利用 JDBC 驱动来查询数据库代码如下:

Class.forName("com.mysql.jdbc.Driver");//加载及注册JDBC驱动程序
String url = "jdbc:mysql://localhost:3306/sample_db?user=root&password=your_password";
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();
String query = "select * from test";
ResultSet rs=stmt.executeQuery(query);
while(rs.next()) {
  rs.getString(1);
  rs.getInt(2);
}

在执行Class.forName("com.mysql.jdbc.Driver");这条语句的时候


package com.mysql.jdbc;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
  static {
    try {
      java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }

  /**
   * Construct a new driver and register it with DriverManager
   * @throws SQLException if a database error occurs.
   */
  public Driver() throws SQLException {
    // Required for Class.forName().newInstance()
  }
}

在静态初始代码块里,调用java.sql.DriverManager.registerDriver将自己‘桥接’上了DriverManager

结合DriverManager的代码来看


public class DriverManager {
  private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<DriverInfo>();

  //...
  static {
    loadInitialDrivers();
    println("JDBC DriverManager initialized");
  }
  //...

  public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {
    if (driver != null) {
      registeredDrivers.addIfAbsent(new DriverInfo(driver));
    } else {
      throw new NullPointerException();
    }
  }

  public static Connection getConnection(String url, String user, String password) throws SQLException {
    java.util.Properties info = new java.util.Properties();
    if (user != null) {
      info.put("user", user);
    }
    if (password != null) {
      info.put("password", password);
    }
    return (getConnection(url, info, Reflection.getCallerClass()));
  }
  //...
}

DriverManager#registerDriver方法接收实现了Driver接口的对象,这就是可以灵活切换 Driver 的原因。

业界经典实现

  • JDBC