目录
前言
如果实现一个跨平台的软件,那么如何处理与平台有关的部分和与平台无关部分,也就是抽象和实现的关系,这里就涉及到Bridge桥接模式了。
1 定义
将抽象部分和实现部分分离,使他们可以独立变化
2 适用性
- 不希望抽象和实现之前被绑定,如希望实现部分可以动态的切换。
- 希望类的实现子类和抽象接口实现可以方便组合和扩充。
- 通常客户实现抽象部分,希望实现部分的修改不影响客户代码的修改编译。
- 希望对客户因此抽象的实现部分,只提供对于实现接口。
3 结构
3.1 结构图
以数据库驱动为示例结构图如下:
3.2 参与者
- Abstraction:抽象接口,可以根据需要进行定制处理
- Implementer:实现部分接口
- ConcreteImplementer:具体实现,可以根据不同厂家,不同平台有不同的实现。
- ConcreteAbstract:客户的抽象实现。
Abstraction在需要使将请求转发到Implementer的实现。
4 Java实际应用举例
数据库驱动的设计可以看作Bridge模式。
4.1 Abstraction——DriverManager
该类定义如下:
public class DriverManager {
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
public static void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if (driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
if (callerCL == null || callerCL == ClassLoader.getPlatformClassLoader()) {
callerCL = Thread.currentThread().getContextClassLoader();
}
if (url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
ensureDriversInitialized();
// Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if (isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
在registeredDrivers中管理注册的Driver,并通过getConnection获取实现类的连接方法。
4.2 Implementer——java.sql.Driver
驱动接口:
定义驱动连接方法等等。
4.3 ConcreteImplementer——com.mysql.cj.jdbc.Driver
具体定义如下:
主要在static完成驱动注册,连接逻辑封装在NonRegisteringDriver中。
5 总结
通常当我们需要将客户与平台无关代码和与平台有关的工具实现分离时,可以采取桥接模式
参考文献
[1]. 《设计模式》