桥接模式在开源代码中的应用
16lz
2021-01-22
桥接模式的作用:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
案例
桥接模式比较经典的应用就是 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,也可以独立变化。
更多相关文章
- 详解第三种创建线程的方式-Callable接口
- 【编测编学】接口测试面试题必背(下)
- 快速测试 API 接口的新技能
- 「Jenkins」- 使用接口批量创建任务
- Java 抽象类与接口的区别
- Swagger 自动生成 Dubbo 服务的接口文档,以及测试调用
- 为什么我们要面向接口编程?!
- jQuery UI框架的Dreamweaver接口
- NodeList接口,HTMLCollection接口