mysql桥梁模式_结构型—桥接(Bridge)模式
发布日期:2021-08-19 23:52:17 浏览次数:10 分类:技术文章

本文共 4507 字,大约阅读时间需要 15 分钟。

1、意图:

将抽象部分(抽象接口)与它的实现部分(代码实现)分离,使它们都可以独立地变化。

理解:抽象部分是对外展现的接口(api),而实现部分是针对抽象接口提供的不同版本的功能实现,使两者独立变化指两者可以在各自的维度上自由变化,而不会产生太大的影响。如可以在api中添加新的接口,而不影响具体实现部分;可以在实现部分针对特定接口添加新的实现方式,而不影响抽象接口定义。

桥接模式将类的继承关系转变为类的聚合关系(见下图)。对于抽象接口及其实现,Java中通常的实现方式是通过抽象类的继承或接口的实现,但是桥接模式,将这种抽象接口与实现之间的关系变成了聚合关系。

2、桥接模式(也称:桥梁模式)类图

f1cf7d5d2f66930ba4c97c7560f25651.png

角色:

Abstraction:定义抽象接口,对外提供api;自身维护一个Implementor(桥)的引用,使用Implementor的操作来完成自身接口功能,如operation方法通过impl.doOperation()来实现;

RefinedAbstraction:扩展Abstraction的抽象接口;

Implementor:架在抽象接口与不同实现方式之间的桥,且自身的接口不必与Abstraction完全相同;

ConcreteImplementorA:实现Implementor(桥)的接口,针对Implementor(桥)中的接口doOperation提供特色化的实现;

Client:用户类。

协作:

Client调用Abstraction提供的接口,而Abstraction将Client的调用通过Implementor来实现。

3、JDBC与桥接:

JDBC是桥接模式的典型实现。

先看下类图:

e6ed5f355cb0922f517ea49031b66321.png

通常使用JDBC连接数据库时,会使用如下代码:

1 Class.forName("数据库类驱动器");2 Connection conn = DriverManager.getConnection("数据库url", "用户名", "密码");3 //.................

针对不同的数据库,JDBC都可以通过java.sql.DriverManager类的静态方法getConnection(数据库url, 用户名, 密码)来获取数据库的连接。JDBC通过DriverManager对外提供了操作数据库的统一接口getConnection,通过该方法可以获取不同数据库的连接,并且通过Connection类提供的接口来进行数据的查询操作。

JDBC为不同的数据库操作提供了相同的接口,但是JDBC本身并没有针对每种数据库提供一套具体实现代码,而是通过接口java.sql.Driver的connect方法连接到了不同的数据库实现。

1 public interfaceDriver2 {3

4 public abstract Connection connect(String s, Properties properties) throwsSQLException;5 //其他方法

6

7 }

在JDBC中,针对不同数据库提供的统一的操作接口通过java.sql.Driver(桥)连接到了不同的数据库实现。如连接mysql数据库。

1 packagecom.mysql.jdbc;2

3 public class NonRegisteringDriver implementsjava.sql.Driver //对java.sql.Driver接口提供了实现4 {5

6 publicConnection connect(String url, Properties info)7 throwsSQLException8 {9 //实现

10 }11

12 //其他方法

13 }

Java在连接MySQL时需要使用mysql-connector-java.jar,mysql-connector-java.jar包提供了对MySQL数据库操作的具体实现,并通过接口Driver连接到了JDBC统一的api。

4、JDBC中桥接模式具体如何实现?

既然,针对不同的数据库,通过DriverManger.getConnection()可以获得相同的Connection接口,那先看DriverManager的源码:

1 public classDriverManager2 {3 private static final CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList(); //存放DriverInfo的链表

4

5 public static synchronized voidregisterDriver(Driver driver)6 throwsSQLException7 {8 if(driver != null)9 registeredDrivers.addIfAbsent(new DriverInfo(driver)); //向链表中添加DriverInfo实例,DriverInfo封装了Driver

10 else

11 throw newNullPointerException();12 println((new StringBuilder()).append("registerDriver: ").append(driver).toString());13 }14

15 private staticConnection getConnection(String s, Properties properties, Class class1)16 throwsSQLException17 {18 //.....

19 Iterator iterator = registeredDrivers.iterator(); //遍历registeredDrivers表

20 do

21 {22 if(!iterator.hasNext())23 break;24 DriverInfo driverinfo =(DriverInfo)iterator.next();25 if(isDriverAllowed(driverinfo.driver, classloader))26 try

27 {28 Connection connection = driverinfo.driver.connect(s, properties); //调用Driver接口提供的connect方法来获取Connection对象

29 if(connection != null)30 {31 returnconnection;32 }33 }34 catch(SQLException sqlexception1)35 {36 if(sqlexception == null)37 sqlexception =sqlexception1;38 }39 } while(true);40 }41

42 //其他方法

43

44 }45

46

从DriverManager.getConnection()源码可见,方法中遍历了包含DriverInfo实例的表registeredDrivers,通过表中实例driverinfo来获取封装的java.sql.Driver类型的实例,并调用java.sql.Driver接口的connect方法获取到Connection。

【注:DriverInfo是Driver的封装类。由DriverInfo源码可见。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 classDriverInfo2 {3

4 DriverInfo(Driver driver1)5 {6 driver =driver1;7 }8

9 public booleanequals(Object obj)10 {11 return (obj instanceof DriverInfo) && driver ==((DriverInfo)obj).driver;12 }13

14 public inthashCode()15 {16 returndriver.hashCode();17 }18

19 publicString toString()20 {21 return (new StringBuilder()).append("driver[className=").append(driver).append("]").toString();22 }23

24 finalDriver driver;25 }

View Code

那么,Driver实例是何时注入到DriverManager类的registeredDrivers中的呢?以mysql为例,在每次使用JDBC连接mysql时,都会有下面的调用:

1 Class.forName("com.mysql.jdbc.Driver");

该行代码通过反射加载了com.mysql.jdbc.Driver类(com.mysql.jdbc.Driver类在mysql-connector-java.jar中,而mysql-connector-java.jar是JDBC连接MySQL的jar包),查看com.mysql.jdbc.Driver类:

1 packagecom.mysql.jdbc;2

3 public class Driver extendsNonRegisteringDriver4 implementsjava.sql.Driver5 {6

7 publicDriver()8 throwsSQLException9 {10 }11

12 static

13 {14 try

15 {16 DriverManager.registerDriver(new Driver());17 }18 catch(SQLException E)19 {20 throw new RuntimeException("Can't register driver!");21 }22 }23 }

在com.mysql.jdbc.Driver的源码中可以看到在加载com.mysql.jdbc.Driver类时,通过类中的静态域中的红色代码,会调用DriverManager的registerDriver方法将当前MySQL的驱动类实例注入到DriverManager的registeredDrivers中。

通过整个代码调用,展示了桥接模式在JDBC中是如何运用的。

5、适用性:

当不希望抽象接口和实现部分采用固定的绑定关系时;

6、特点:

桥接模式良好地实现了开闭原则:通常应用桥接模式的地方,抽象接口和具体实现部分都是可以变化的,且抽象接口与实现耦合度低;

桥接模式将类继承关系转换成了对象组合关系,实现了类的复用,减少了类的个数。

转载地址:https://blog.csdn.net/weixin_31414801/article/details/113614544 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python删除元组中的元素del_Python 元组(Tuple)操作详解
下一篇:mysql 多个列拼接_mysql 多个字段拼接

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月03日 09时00分25秒