桥接模式在开源代码中的应用

2020-07-25

桥接模式的作用:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

 

案例

桥接模式比较经典的应用就是 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;
        }
    }
}

 

示意图:

ConstXiong 备案号:苏ICP备16009629号-3