JDBC之桥接模式

先说说桥接模式,桥接模式的特点是将实现和抽象进行分离,进行解耦。
抽象实现分离,使它们可以独立变化。它是用组合/聚合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

桥接模式的基本结构

  • Abstraction — 抽象化角色:
    定义抽象的接口,包含一个对实现化角色的引用

  • Refined Abstraciotn — 扩展抽象化角色:
    抽象化角色的子类,实现父类中的业务方法,并通过组合/聚合关系调用实现化角色中的业务方法

  • Implementor — 实现化角色:
    定义具体行为、具体特征的应用接口,供扩展抽象化角色使用

  • Concrete Implemetor — 具体实现化角色:
    实现化角色的具体实现

实例一:模拟毛笔

现需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。本实例使用桥接模式来模拟毛笔的使用过程。


image.png

JDBC中的桥接模式

JDBC中也分为两个维度的变化,一个是:Driver ,一个是Connection.

源码解析
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://:/");

Class.forName()反射的三种方式之一,返回java.lang.Class对象,用于在程序运行时的某个时刻,由客户端调用,动态加载该类或该接口到当前线程中。
MySQL源码中:com.mysql.cj.jdbc.Driver类
com.mysql.cj.jdbc.Driver类仅包含一段静态代码,其中最关键的是静态代码段中的 DriverManager.registerDriver(new Driver()) ,它会在客户端调用Class.forName()方法加载com.mysql.cj.jdbc.Driver类的同时被执行,Driver类自身的一个实例被注册到DriverManager(即保存到DriverManager的静态字段registeredDrivers内)。
DriverManager类部分源码

public class DriverManager {
    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();
    private static volatile int loginTimeout = 0;
    private static volatile java.io.PrintWriter logWriter = null;
    private static volatile java.io.PrintStream logStream = null;
    // Used in println() to synchronize logWriter
    private final static  Object logSync = new Object();

Class.forName()方法调用后,com.mysql.cj.jdbc.Driver类被加载,并执行static { } 静态代码段,将com.mysql.cj.jdbc.Driver类实例注册到DriverManager中。然后,客户端会调用DriverManager.getConnection()方法获取一个Connection数据库连接实例,该方法的部分源码如下:

 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和数据库之间的连接,如果全部失败,就抛出异常提示连接失败。

Connection接口

DriverManager.getConnection()方法返回的Connection数据库连接实例根据不同的数据库有不同的实现。
这是变化的第二个维度。


image.png

你可能感兴趣的:(JDBC之桥接模式)