理解名称
桥接模式(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