iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java的JDBC和桥接模式详解
  • 484
分享到

Java的JDBC和桥接模式详解

2024-04-02 19:04:59 484人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录本文参考桥接模式的定义与特点定义:优点:缺点:桥接模式的基本结构桥接模式的应用场景JDBC源码剖析Class.forName()方法com.Mysql.cj.jdbc.Drive

本文参考

网上对于JDBC与桥接模式的理解各有不同,在这片文章里提出的是我个人对于二者的理解,本文参考的其它博文如下:

https://www.jb51.net/article/217763.htm

Https://www.jb51.net/article/112714.htm

https://www.jb51.net/article/137835.htm

http://edu.jb51.net/design-pattern/design-pattern-bridge.html

桥接模式的定义与特点

定义:

将抽象与实现分离,使它们可以独立变化。它是用组合/聚合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。例如针对一个图形,我们可以设计颜色和形状两个变化维度

优点:

由于抽象与实现分离,所以扩展能力强;实现细节对客户透明

缺点:

由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度

桥接模式的基本结构

Abstraction — 抽象化角色:

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

Refined Abstraciotn — 扩展抽象化角色:

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

Implementor — 实现化角色:

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

Concrete Implemetor — 具体实现化角色

实现化角色的具体实现

基本的模式结构类图如下:

桥接模式的应用场景

  • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时
  • 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
  • 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时

JDBC源码剖析

在不使用spring、Hibernate等第三方库的情况下,直接通过原生JDBC api连接mysql数据库,则有如下示例代码:


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

短短两行代码难以看出桥接模式的结构,下面先对源码进行一定的分析,理解各个类和接口之间的关系

Class.forName()方法

该方法将返回与给定字符串名的类或接口相关联的java.lang.Class类对象,用于在程序运行时的某个时刻,由客户端调用,动态加载该类或该接口到当前线程

Returns the Class object associated with the class or interface with the given string name.
Given the fully qualified name for a class or interface this method attempts to locate, load, and link the class or interface.

若Class.forName()加载的是一个类,也会执行类中包含的static { } 静态代码段

com.mysql.cj.jdbc.Driver类

MySQL将具体的java.sql.Driver接口的实现放到了NonReGISteringDriver中,com.mysql.cj.jdbc.Driver类仅包含一段静态代码,具体类图如下:

其中最关键的是静态代码段中的 DriverManager.registerDriver(new Driver()) ,它会在客户端调用Class.forName()方法加载com.mysql.cj.jdbc.Driver类的同时被执行,Driver类自身的一个实例被注册到DriverManager(即保存到DriverManager的静态字段registeredDrivers内),注册过程的源码如下:


public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da)
throws SQLException {
  
  if(driver != null) {
    registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
  } else {
    // This is for compatibility with the original DriverManager
    throw new NullPointerException();
  }
  println("registerDriver: " + driver);
}

registeredDrivers静态字段的类型是实现了List接口的CopyOnWriteArrayList类,它能够保存进一步封装java.sql.Driver接口的DriverInfo类实例,DriverInfo类的声明代码如下:


class DriverInfo {
  final Driver driver;
  DriverAction da;
  DriverInfo(Driver driver, DriverAction action) {
    this.driver = driver;
    da = action;
  }
  // ……
}

引申:

DriverInfo还包装了DriverAction,DriverAction会在Driver被取消注册时被调用,DriverAction的源码注释如下:

The JDBC driver's static initialization block must call DriverManager.registerDriver(Driver, DriverAction) in order to infORM DriverManager which DriverAction implementation to call when the JDBC driver is de-registered.

MySQL的Driver在向DriverManager进行注册时,DriverAction被设置为null

DriverManager类

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


private static Connection getConnection(String url, java.util.Properties info, Class<?> caller) throws SQLException {
  // ……
  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());
    }
  }
  // ……
}

DriverManager.getConnection()方法会遍历registeredDrivers静态字段,获取字段内保存的每一个Driver来尝试响应客户端的数据库连接请求,若所有Driver都连接数据库失败,则提示连接失败信息

Connection接口

Connection代表和特定数据库的连接会话,能够执行SQL语句并在连接的上下文中返回执行结果。

A connection (session) with a specific database. SQL statements are executed and results are returned within the context of a connection.

因此,DriverManager.getConnection()方法返回的Connection数据库连接实例根据不同的数据库有不同的实现,MySQL的Connection接口实现关系如下:

源码类图

根据源码的分析,绘制类图如下:

对Driver和Connection进行抽象,绘制类图如下:

模式体现

桥接模式通过组合/聚合关系代替继承关系,实现抽象化和实现化部分的解耦。以上述JDBC在MySQL中的简略类图为例,抽象化部分有Driver接口和Connection接口,实现化部分有DriverManager。对于不同的数据库,Driver接口和Connection接口都有自己独特的实现类

但是,和Driver接口不同的是,Connection接口与DriverManager类的关系只是联系较弱的依赖关系,并不符合桥接模式的定义和特点。因此,在考虑桥接模式的情况下,可以再次将类图进行简化:

最后,我们将其它数据库的Driver接口实现也考虑在内,绘制类图如下:

桥接模式中的实现化(Implementor)角色对应上图的Driver接口,具体实现化(Concrete Implementor)角色对应MysqlDriver、oracleDriver和MariadbDriver,扩展抽象化 (Refined Abstraction)角色对应DriverManager,不具有抽象化(Abstraction)角色作为扩展抽象化角色的父类

桥接模式的主要应用场景是某个类存在两个独立变化的维度,且这两个维度都需要进行扩展,而现在仅有Driver一个变化维度,DriverManager没有抽象化父类,它本身也没有任何子类,因此我认为,在JDBC中,是一种简化的桥接模式 —— 观点一。

倘若JDBC针对Connection接口的设计不是将它作为Driver和DriverManager的"依赖"来处理,而是也作为一个变化的维度加入到桥接模式,或许能够更好地体现JDBC对桥接模式的实现,一种"假想"的桥接模式如下:

其它观点二:JDBC采用的是策略模式而不是桥接模式

问题源自知乎,但是没有任何人做出解答,因为这确实和策略模式十分相似,如果把桥接模式的抽象部分简化来看,不去设计Abstraction,也就是用Refined Abstraction代替Abstraction,那么就类似于策略模式的Context来使用接口的对象

但是,桥接模式和策略模式的目的是不一样的,策略模式属于对象行为模式(描述对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责),它的目的是封装一系列的算法,使得算法可以相互替代,并在程序运行的不同时刻选择合适的算法。而桥接模式属于对象结构模式(描述如何将对象按某种布局组成更大的结构),它的目的是将抽象与实现分离,使它们可以独立变化

因此,从设计的目的来看,JDBC采用的并不是策略模式,在一段程序中数据库驱动并不存在频繁地相互替换

其它观点三:变化的维度一个是平台,另一个是数据库

这是我认同的一个观点,引用原文的话

变的是平台和数据库,平台在JVM这个层面就解决了,因为所有操作系统java基本都会提供对应jdk,这也是"Once Write,Run AnyWhere"的原因。而数据库则是依托公司的具体实现,各个公司都提供对应的Driver类,我用DriverManager类进行懒加载

考虑数据库的实际应用场景,我们可能在不同的操作系统上使用不同的数据库,但是JVM的平台无关性使得我们不再有操作系统层面上的变化。假设不存在JVM,那么不同的客户端加载和运行数据库驱动程序的代码自然也各有不同,即DriverManager会因操作系统的变化而变化,不同的操作系统可以有不同的注册Driver的方式

不过因为存在JVM,我们现在不再有"平台"这一变化维度了

其它观点四:变化的维度一个是客户端应用系统,另一个是数据库

一个比较独特的观点,引用原文的话

应用系统作为一个等级结构,与JDBC驱动器这个等级结构是相对独立的,它们之间没有静态的强关联。应用系统通过委派与JDBC驱动器相互作用,这是一个桥梁模式的例子。

原文笔者不认为DriverManager作为Refined Abstraction角色存在,而是视作两个变化维度之间的一个"过渡",原本的"桥"是Abstraction和Implementor之间的组合/聚合关系,而现在DriverManager类本身成为了"桥",可以看作是桥梁模式的一个变体

新的观点五:变化的维度一个是Driver,一个是Connection

如果从观点四的原文笔者的角度看,把DriverManager类本身作为"桥",那么我们还可以提出一种新的观点,绘制类图如下:

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: Java的JDBC和桥接模式详解

本文链接: https://www.lsjlt.com/news/135933.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java的JDBC和桥接模式详解
    目录本文参考桥接模式的定义与特点定义:优点:缺点:桥接模式的基本结构桥接模式的应用场景JDBC源码剖析Class.forName()方法com.mysql.cj.jdbc.Drive...
    99+
    2024-04-02
  • java设计模式--桥接模式详解
    目录引例桥接模式实战示例代码:总结引例 需求:对不同手机类型的不同品牌(比如按键手机:诺基亚、翻盖手机:纽曼、智能手机:华为、小米)实现操作编程(比如: 开机、关机、打电话)。 先来...
    99+
    2024-04-02
  • Java设计模式之java桥接模式详解
    目录一、什么是桥接模式:二、UML结构图:三、代码实现:四、JDBC源码解析-桥接模式:1、源码分析:2、源码类图:3、对 JDBC 的观点:参考博客:总结一、什么是桥接模式: 桥接...
    99+
    2024-04-02
  • 详解Java设计模式之桥接模式
    目录一、什么是桥接模式:二、UML结构图三、代码实现四、JDBC源码解析-桥接模式1、源码分析2、源码类3、对 JDBC 的观点一、什么是桥接模式: 桥接,顾名思义,就是用来连接两个...
    99+
    2024-04-02
  • Java结构型模式之桥接模式详解
    目录一.介绍二.场景理解三.UML类图四.具体代码五.优缺点六.使用场景一.介绍 桥接模式(Bridge Pattern)属于结构型模式。用于将抽象与其实现解耦,使得二者可以独立变化...
    99+
    2023-02-17
    Java结构型模式 Java桥接模式
  • 设计模式——桥接模式详解
    🚀桥接模式(抽象与实现分离) 1.1⭐桥接模式的定义 维基百科:桥接模式是软件设计模式中最复杂的模式之一,它把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。 百度百...
    99+
    2023-10-11
    设计模式 桥接模式 java
  • Java设计模式之桥接模式的示例详解
    目录定义案例需求方案一方案二对比分析总结定义 桥梁模式是对象的结构模式。又称为柄体(Handle and Body)模式或接口(Interface)模式。桥梁模式的用意是&ldquo...
    99+
    2024-04-02
  • 详解PHP设计模式之桥接模式
    目录简介适用场景优点缺点扩展案例代码抽象代码简介 桥接模式又叫桥梁模式,属于结构型模式。目的是将抽象与实现分离,使它们都可以独立的变化,解耦。继承有很多好处,但是会增加耦合,而桥接模...
    99+
    2022-12-20
    PHP桥接模式 PHP设计模式
  • Java设计模式中的桥接模式
    目录模式介绍UML类图桥接模式案例桥接模式的注意事项和细节常见的应用场景模式介绍 桥接模式(Bridge模式)是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。是一种...
    99+
    2024-04-02
  • 如何理解Java设计模式的桥接模式
    这篇文章主要讲解了“如何理解Java设计模式的桥接模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java设计模式的桥接模式”吧!一、什么是桥接模式桥接模式(Bridge Patt...
    99+
    2023-06-25
  • Java结构型设计模式之桥接模式详细讲解
    目录桥接模式概述应用场景优缺点主要角色桥接模式的基本使用创建实现角色创建具体实现角色创建抽象角色创建修正抽象角色客户端调用桥接模式实现消息发送创建实现角色创建具体实现角色创建抽象角色...
    99+
    2024-04-02
  • Java设计模式之桥接模式
    本文通过老王和小王买车,引出设计模式中的结构型设计之桥接模式,接着说明设计型模式的概念和代码实现,为了加深理解,会说明适配器设计模式在JDBC中的应用,最后谈谈桥接模式和适配器模式的...
    99+
    2024-04-02
  • Golang设计模式中的桥接模式详细讲解
    目录桥接模式概念示例桥接模式 桥接是一种结构型设计模式, 可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。 层次结构中的第一层 (通常称为抽象部分) 将包含对第二...
    99+
    2023-01-11
    Go桥接模式 Go设计模式
  • 深入理解Java设计模式之桥接模式
    目录二、桥接模式的结构三、桥接模式的使用场景四、桥接模式的优缺点五、装饰,桥接和适配器模式的异同适配器模式:桥接模式:装饰器模式:六、桥接模式的实现七、总结一、什么是桥接模式 桥接模...
    99+
    2024-04-02
  • Java设计模式之桥接模式的实现
    桥接模式 桥接模式是将抽象部分与它的实现部分分离,使他们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。 ...
    99+
    2024-04-02
  • java中的桥接模式是什么
    本篇内容主要讲解“java中的桥接模式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java中的桥接模式是什么”吧!目录引例桥接模式实战示例代码:总结引例需求:对不同手机类型的不同品牌(比...
    99+
    2023-06-20
  • Java怎么实现桥接模式
    本文小编为大家详细介绍“Java怎么实现桥接模式”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java怎么实现桥接模式”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。桥接模式(Bridge Pattern)是用于...
    99+
    2023-06-27
  • Java桥接模式怎么使用
    这篇文章主要介绍“Java桥接模式怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java桥接模式怎么使用”文章能帮助大家解决问题。其实在现实生活中,有很多类可以有两个或多个维度的变化,如图形...
    99+
    2023-06-30
  • java如何实现桥接模式
    这篇文章将为大家详细讲解有关java如何实现桥接模式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。介绍桥接模式 (Bridge)将抽象部分与实现部分分离,使它们都可以独立的变化。桥接模式是一种结构式模式。...
    99+
    2023-05-30
    java
  • Java设计模式的桥接模式怎么实现
    这篇文章主要讲解了“Java设计模式的桥接模式怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java设计模式的桥接模式怎么实现”吧!什么是桥接模式桥接(Bridge)模式的定义如下:...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作