JDBC之橋接模式

先說說橋接模式,橋接模式的特點是將實現(xiàn)和抽象進行分離,進行解耦。
抽象實現(xiàn)分離,使它們可以獨立變化。它是用組合/聚合關(guān)系代替繼承關(guān)系來實現(xiàn),從而降低了抽象和實現(xiàn)這兩個可變維度的耦合度。

橋接模式的基本結(jié)構(gòu)

  • Abstraction — 抽象化角色:
    定義抽象的接口,包含一個對實現(xiàn)化角色的引用

  • Refined Abstraciotn — 擴展抽象化角色:
    抽象化角色的子類,實現(xiàn)父類中的業(yè)務(wù)方法,并通過組合/聚合關(guān)系調(diào)用實現(xiàn)化角色中的業(yè)務(wù)方法

  • Implementor — 實現(xiàn)化角色:
    定義具體行為、具體特征的應(yīng)用接口,供擴展抽象化角色使用

  • Concrete Implemetor — 具體實現(xiàn)化角色:
    實現(xiàn)化角色的具體實現(xiàn)

實例一:模擬毛筆

現(xiàn)需要提供大中小3種型號的畫筆,能夠繪制5種不同顏色,如果使用蠟筆,我們需要準備3*5=15支蠟筆,也就是說必須準備15個具體的蠟筆類。而如果使用毛筆的話,只需要3種型號的毛筆,外加5個顏料盒,用3+5=8個類就可以實現(xiàn)15支蠟筆的功能。本實例使用橋接模式來模擬毛筆的使用過程。


image.png

JDBC中的橋接模式

JDBC中也分為兩個維度的變化,一個是:Driver ,一個是Connection.

源碼解析
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://<host>:<port>/<database>");

Class.forName()反射的三種方式之一,返回java.lang.Class對象,用于在程序運行時的某個時刻,由客戶端調(diào)用,動態(tài)加載該類或該接口到當前線程中。
MySQL源碼中:com.mysql.cj.jdbc.Driver類
com.mysql.cj.jdbc.Driver類僅包含一段靜態(tài)代碼,其中最關(guān)鍵的是靜態(tài)代碼段中的 DriverManager.registerDriver(new Driver()) ,它會在客戶端調(diào)用Class.forName()方法加載com.mysql.cj.jdbc.Driver類的同時被執(zhí)行,Driver類自身的一個實例被注冊到DriverManager(即保存到DriverManager的靜態(tài)字段registeredDrivers內(nèi))。
DriverManager類部分源碼

public class DriverManager {
    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList<DriverInfo> 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()方法調(diào)用后,com.mysql.cj.jdbc.Driver類被加載,并執(zhí)行static { } 靜態(tài)代碼段,將com.mysql.cj.jdbc.Driver類實例注冊到DriverManager中。然后,客戶端會調(diào)用DriverManager.getConnection()方法獲取一個Connection數(shù)據(jù)庫連接實例,該方法的部分源碼如下:

 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和數(shù)據(jù)庫之間的連接,如果全部失敗,就拋出異常提示連接失敗。

Connection接口

DriverManager.getConnection()方法返回的Connection數(shù)據(jù)庫連接實例根據(jù)不同的數(shù)據(jù)庫有不同的實現(xiàn)。
這是變化的第二個維度。


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容