设计模式-桥接模式
桥接模式,也叫作桥梁模式,英文是 Bridge Design Pattern。桥接模式是这么定义的:“Decouple an abstraction from its implementation so that the two can vary independently。”翻译成中文就是:“将抽象和实现解耦,让它们可以独立变化。”
关于桥接模式,很多书籍、资料中,还有另外一种理解方式:“一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。”通过组合关系来替代继承关系,避免继承层次的指数级爆炸。
JDBC 驱动是桥接模式的经典应用。我们先来看一下,如何利用 JDBC 驱动来查询数据库。具体的代码如下所示:
1 | Class.forName("com.mysql.jdbc.Driver");//加载及注册JDBC驱动程序 |
如果我们想要把 MySQL
数据库换成 Oracle
数据库,只需要把第一行代码中的 com.mysql.jdbc.Driver
换成 oracle.jdbc.driver.OracleDriver
就可以了。
不管是改代码还是改配置,在项目中,从一个数据库切换到另一种数据库,都只需要改动很少的代码,或者完全不需要改动代码,那如此优雅的数据库切换是如何实现的呢?
源码之下无秘密。要弄清楚这个问题,我们先从 com.mysql.jdbc.Driver
这个类的代码看起。
1 |
|
结合 com.mysql.jdbc.Driver
的代码实现,我们可以发现,当执行 Class.forName(“com.mysql.jdbc.Driver”)
这条语句的时候,实际上是做了两件事情。第一件事情是要求 JVM
查找并加载指定的 Driver
类,第二件事情是执行该类的静态代码,也就是将 MySQL Driver 注册到 DriverManager
类中。
现在,我们再来看一下,DriverManager
类是干什么用的。具体的代码如下所示。当我们把具体的 Driver
实现类(比如,com.mysql.jdbc.Driver
)注册到 DriverManager
之后,后续所有对 JDBC
接口的调用,都会委派到对具体的 Driver
实现类来执行。而 Driver
实现类都实现了相同的接口(java.sql.Driver
),这也是可以灵活切换 Driver
的原因。
1 |
|
桥接模式的定义是“将抽象和实现解耦,让它们可以独立变化”。那弄懂定义中“抽象”和“实现”两个概念,就是理解桥接模式的关键。那在 JDBC 这个例子中,什么是“抽象”?什么是“实现”呢?
实际上,JDBC
本身就相当于“抽象”。注意,这里所说的“抽象”,指的并非“抽象类”或“接口”,而是跟具体的数据库无关的、被抽象出来的一套“类库”。具体的 Driver
(比如,com.mysql.jdbc.Driver)就相当于“实现”。注意,这里所说的“实现”,也并非指“接口的实现类”,而是跟具体数据库相关的一套“类库”。JDBC
和 Driver
独立开发,通过对象之间的组合关系,组装在一起。JDBC
的所有逻辑操作,最终都委托给 Driver
来执行。