桥接模式的作用:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
案例
桥接模式比较经典的应用就是 JDBC 规范和不同数据库厂商驱动的实现
JDBC 中的驱动接口
public interface Driver {
Connection connect(String url, java.util.Properties info) throws SQLException;
boolean acceptsURL(String url) throws SQLException;
.
.
.
}
JDBC 中的驱动管理器
public class DriverManager {
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
private DriverManager(){}
public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException {
if(driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
throw new NullPointerException();
}
}
private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
SQLException reason = null;
for(DriverInfo aDriver : registeredDrivers) {
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
}
}
.
.
.
}
}
MySQL 的 Driver 继承的 NonRegisteringDriver 类
package com.mysql.jdbc;
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!");
}
}
public Driver() throws SQLException {
}
}
MySQL 的 NonRegisteringDriver 对 JDBC 中的 Driver 接口进行实现
public class NonRegisteringDriver implements java.sql.Driver {
private static final String ALLOWED_QUOTES = "\"'";
private static final String REPLICATION_URL_PREFIX = "jdbc:mysql:replication://";
private static final String URL_PREFIX = "jdbc:mysql://";
.
.
.
public java.sql.Connection connect(String url, Properties info) throws SQLException {
.
.
.
try {
Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(host(props), port(props), props, database(props), url);
return newConn;
} catch (SQLException sqlEx) {
throw sqlEx;
} catch (Exception ex) {
SQLException sqlEx = SQLError.createSQLException(
Messages.getString("NonRegisteringDriver.17") + ex.toString() + Messages.getString("NonRegisteringDriver.18"),
SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);
sqlEx.initCause(ex);
throw sqlEx;
}
}
}
示意图:
JDBC 中 Driver 接口就是抽象部分,每个厂商有自己的实现,独立变化;JDBC 中 DriverManager 类通过组合的方式,持有注册进来的 Driver 对象,对应用系统提供数据库操作的 API,也可以根据需求独立变化。
【Java学习资源】整理推荐
- 桥接模式在开源代码中的应用
- 适配器模式在开源代码中的应用
- 代理模式在开源代码中的应用
- 原型模式在开源代码中的应用
- 建造者模式在开源代码中的应用
- 工厂模式在开源代码中的应用
- 单例模式在开源代码中的应用
- 编码规范
- 设计模式
- 重构
- 设计原则
- 面向对象到底是什么
- 代码质量有哪些评判标准?