桥接模式详解和分析JDBC中的应用

news/2024/9/18 23:40:11/ 标签: 桥接模式, java, java-ee, spring boot, 数据库

🎯 设计模式专栏,持续更新中, 欢迎订阅:JAVA实现设计模式
🛠️ 希望小伙伴们一键三连,有问题私信都会回复,或者在评论区直接发言

桥接模式

文章目录

  • 桥接模式
    • 桥接模式的四个核心组成:
    • 案例:电视与遥控器的桥接模式
    • ⚙️代码实现
      • Step 1: 实现 `TV` 接口 (Implementor)
      • Step 2: 创建 `SonyTV` 和 `SamsungTV` 类 (Concrete Implementor)
      • Step 3: 创建 `RemoteControl` 类 (Abstraction)
      • Step 4: 创建 `SonyRemoteControl` 和 `SamsungRemoteControl` (Refined Abstraction)
      • 🌟 Main函数展示桥接模式的使用
    • 源码应用
    • 📜 总结:

桥接模式(Bridge Pattern)是一种结构型设计模式,目的是将抽象部分与它的实现部分分离开来,使它们可以独立变化。这种模式通过组合的方式(而不是继承)将不同的维度分离,使代码更加灵活、易于扩展。

简单说法: 想象你有一个电视遥控器,遥控器负责打开/关闭电视、调节音量等操作。而不同品牌的电视(如索尼、三星)可能实现这些操作的方式不一样。桥接模式允许你在不修改遥控器代码的情况下,切换或扩展不同品牌的电视。遥控器和电视品牌之间使用接口桥接,使得它们可以独立变化。

桥接模式的四个核心组成:

  1. Abstraction(抽象部分):高层接口,定义抽象的操作,如遥控器的功能(打开、关闭、调音量等)。
  2. Refined Abstraction(扩展抽象部分):扩展自Abstraction,定义更具体的遥控器类型。
  3. Implementor(实现部分):具体实现接口,不同的实现类可以完成具体操作(不同品牌电视的功能实现)。
  4. Concrete Implementor(具体实现部分):Implementor的具体实现,如SonyTV和SamsungTV。

案例:电视与遥控器的桥接模式

你有一个通用的遥控器,可以操作不同品牌的电视,遥控器定义了on()off()setChannel()等功能,而每个品牌的电视实现这些功能的细节可能不同。通过桥接模式,我们将遥控器和电视品牌分离,便于扩展。

UML类图结构

java">Abstraction                    ImplementorRemoteControl   ---->    TV/     \                    /    \
Concrete    SonyRemote   SonyTV  SamsungTV
Abstraction                ConcreteImplementor

⚙️代码实现

Step 1: 实现 TV 接口 (Implementor)

java">// TV接口定义基本操作
interface TV {void on();void off();void setChannel(int channel);
}

Step 2: 创建 SonyTVSamsungTV 类 (Concrete Implementor)

java">// SonyTV 具体实现类
class SonyTV implements TV {@Overridepublic void on() {System.out.println("Sony TV is now ON");}@Overridepublic void off() {System.out.println("Sony TV is now OFF");}@Overridepublic void setChannel(int channel) {System.out.println("Sony TV: Channel set to " + channel);}
}// SamsungTV 具体实现类
class SamsungTV implements TV {@Overridepublic void on() {System.out.println("Samsung TV is now ON");}@Overridepublic void off() {System.out.println("Samsung TV is now OFF");}@Overridepublic void setChannel(int channel) {System.out.println("Samsung TV: Channel set to " + channel);}
}

Step 3: 创建 RemoteControl 类 (Abstraction)

java">// 遥控器抽象类,组合TV接口
abstract class RemoteControl {protected TV tv;// 通过构造方法传递TV对象,形成桥接public RemoteControl(TV tv) {this.tv = tv;}public abstract void on();public abstract void off();public abstract void setChannel(int channel);
}

Step 4: 创建 SonyRemoteControlSamsungRemoteControl (Refined Abstraction)

java">// 扩展的具体遥控器类,使用不同的TV实现
class SonyRemoteControl extends RemoteControl {public SonyRemoteControl(TV tv) {super(tv);}@Overridepublic void on() {System.out.println("Using Sony Remote Control:");tv.on();}@Overridepublic void off() {System.out.println("Using Sony Remote Control:");tv.off();}@Overridepublic void setChannel(int channel) {System.out.println("Using Sony Remote Control:");tv.setChannel(channel);}
}class SamsungRemoteControl extends RemoteControl {public SamsungRemoteControl(TV tv) {super(tv);}@Overridepublic void on() {System.out.println("Using Samsung Remote Control:");tv.on();}@Overridepublic void off() {System.out.println("Using Samsung Remote Control:");tv.off();}@Overridepublic void setChannel(int channel) {System.out.println("Using Samsung Remote Control:");tv.setChannel(channel);}
}

🌟 Main函数展示桥接模式的使用

java">public class BridgePatternDemo {public static void main(String[] args) {// 创建不同品牌的电视TV sonyTV = new SonyTV();TV samsungTV = new SamsungTV();// 使用Sony Remote控制Sony TVRemoteControl sonyRemote = new SonyRemoteControl(sonyTV);sonyRemote.on();sonyRemote.setChannel(5);sonyRemote.off();System.out.println("-------------");// 使用Samsung Remote控制Samsung TVRemoteControl samsungRemote = new SamsungRemoteControl(samsungTV);samsungRemote.on();samsungRemote.setChannel(10);samsungRemote.off();}
}

运行结果:

java">Using Sony Remote Control:
Sony TV is now ON
Using Sony Remote Control:
Sony TV: Channel set to 5
Using Sony Remote Control:
Sony TV is now OFF
-------------
Using Samsung Remote Control:
Samsung TV is now ON
Using Samsung Remote Control:
Samsung TV: Channel set to 10
Using Samsung Remote Control:
Samsung TV is now OFF

源码应用

JDBC中的桥接模式源码探索:

背景:
在Java的数据库连接(JDBC)中,JDBC API 提供了统一的数据库操作接口,而具体的数据库操作实现则由各数据库厂商的驱动(Driver)实现。这里,JDBC API 是抽象部分,而每个数据库驱动则是具体实现部分。

桥接模式分析:

  • Abstraction(抽象部分): java.sql.DriverManager 提供了一个统一的接口,用于注册不同数据库的驱动。
  • Implementor(实现部分): 各个数据库驱动(例如MySQL、PostgreSQL、Oracle等),分别通过实现 java.sql.Driver 接口来具体执行数据库连接操作。

桥接效果:
程序员只需基于统一的JDBC接口操作数据库,而无需关心底层数据库具体如何实现连接。通过桥接模式,可以轻松扩展或替换不同的数据库驱动,而不影响客户端代码。

代码使用示例:

java">Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");

DriverManager 在内部会根据传入的 JDBC URL 查找合适的 Driver 来建立数据库连接,这样就将抽象的 Connection 操作与具体的数据库实现分离。

🌐 桥接模式的类图

java">+-------------------------------------+                 +--------------------------------+
|          java.sql.Driver            |  <---- Bridge   |  Abstract representation      |
|-------------------------------------|                 | of how to connect to database |
| + connect()                         |                 | using different implementations|
| + acceptURL()                       |                 +--------------------------------+
| + other common methods              |          
+----------------+--------------------+     ^|       Implementor|+-------------------------------+       +------------------------------------+|      com.mysql.cj.jdbc.Driver  |       |    org.postgresql.Driver           |+-------------------------------+       +------------------------------------+| + Implementation of connect()  |       |  + Implementation of connect()     |+-------------------------------+       +------------------------------------+^                                         ^|                                         |+-------------------------------+         ||      java.sql.DriverManager   |          |+-------------------------------+         ||  + registerDriver(Driver d)    |         ||  + getConnection(String url)   |         ||  + other common methods        |         |+-------------------------------+         ||+------------+-------------+|    java.sql.Connection   |+--------------------------+|  + createStatement()      ||  + close()                |+--------------------------+

⚙️ 关键源码解读:

1. Driver 接口(抽象部分,桥接接口)

java">package java.sql;import java.util.Properties;
import java.sql.SQLException;public interface Driver {// 尝试建立数据库连接Connection connect(String url, Properties info) throws SQLException;// 判断Driver是否可以处理传入的URLboolean acceptsURL(String url) throws SQLException;// 获取驱动的相关属性信息DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException;// 获取驱动的主版本号int getMajorVersion();// 获取驱动的次版本号int getMinorVersion();// 检查驱动是否为JDBC规范的合规实现boolean jdbcCompliant();
}

在这个接口中,Driver定义了通用的行为,所有数据库驱动都需要实现这些方法,如 connect()acceptsURL()

2. DriverManager(抽象部分与实现部分的桥梁)

java">package java.sql;import java.util.Enumeration;
import java.util.Vector;
import java.sql.Driver;
import java.sql.SQLException;public class DriverManager {// 注册驱动public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {registeredDrivers.addIfAbsent(new DriverInfo(driver));}// 通过指定URL连接数据库public static Connection getConnection(String url, String user, String password)throws SQLException {java.util.Properties info = new java.util.Properties();info.put("user", user);info.put("password", password);return getConnection(url, info);}// 具体的连接数据库逻辑public static Connection getConnection(String url, java.util.Properties info)throws SQLException {// 遍历已注册的驱动for (DriverInfo aDriver : registeredDrivers) {try {if (aDriver.driver.acceptsURL(url)) {return aDriver.driver.connect(url, info); // 调用驱动的connect方法}} catch (SQLException e) {// 忽略异常,尝试下一个驱动}}throw new SQLException("No suitable driver found for " + url);}// 保持已注册驱动的信息private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();static {// 内部静态代码块加载驱动loadInitialDrivers();}// 省略其他方法
}

解析:

  • DriverManager.registerDriver() 用于注册数据库驱动,开发者无需直接使用具体驱动类来注册。
  • DriverManager.getConnection() 是我们日常使用的API,内部通过调用已注册的 Driver 实现 connect() 方法来建立连接。

桥接模式应用: DriverManager 作为抽象的管理者,通过 Driver 接口的实现来具体连接到不同的数据库,真正实现了抽象和实现的分离。不同的数据库驱动(如MySQL、PostgreSQL等)是 Driver 接口的不同实现,开发者使用统一的 DriverManager.getConnection() 方法进行数据库操作,无需了解底层的实现。

3. com.mysql.cj.jdbc.Driver(具体实现部分)

java">package com.mysql.cj.jdbc;import java.sql.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;public class Driver implements java.sql.Driver {static {try {// 在类加载时自动注册MySQL驱动java.sql.DriverManager.registerDriver(new Driver());} catch (SQLException e) {throw new RuntimeException("Failed to register MySQL driver.", e);}}@Overridepublic Connection connect(String url, Properties info) throws SQLException {// 检查是否支持该URLif (!acceptsURL(url)) {return null;}// 创建与MySQL数据库的连接return new ConnectionImpl(host, port, dbName, user, password);}@Overridepublic boolean acceptsURL(String url) {// 检查URL是否符合MySQL的格式return url.startsWith("jdbc:mysql:");}// 省略其他实现方法...
}

解析:

  • com.mysql.cj.jdbc.DriverDriver 接口的具体实现,通过桥接到 DriverManager,它实现了具体的连接MySQL数据库的逻辑。

  • acceptsURL() 方法判断传入的URL是否是MySQL的格式,connect() 方法则通过该URL与MySQL数据库建立连接。

  • JDBC桥接模式总结:

    • Abstraction(抽象部分): DriverManager 是抽象部分,提供统一的API供开发者使用,它只负责管理和协调不同的 Driver 实现,而不关心具体实现细节。
    • Implementor(实现部分): 各个数据库驱动实现了 Driver 接口,例如 com.mysql.cj.jdbc.Driverorg.postgresql.Driver,它们分别负责与具体的数据库进行交互。

    桥接模式通过分离抽象和实现,使得JDBC API可以轻松支持多种不同的数据库,而开发者只需通过统一的 DriverManager.getConnection() 进行操作。不同数据库的连接实现细节被隐藏在各自的 Driver 实现类中,确保了系统的扩展性和维护性。

📜 总结:

桥接模式让我们能够将抽象部分与具体实现分离,在保持系统灵活的同时,允许独立扩展抽象和实现层次。在上面的例子中,RemoteControlTV 分离,使得你可以轻松扩展更多不同类型的遥控器或电视品牌,而无需修改已有代码。

桥接模式在JDK和各种框架中得到广泛应用,特别是在处理跨平台差异、解耦抽象和实现的场景中。通过桥接模式,能够保持系统的高扩展性和灵活性,便于维护和改进。无论是数据库操作、GUI绘制、日志框架还是视图解析,桥接模式都扮演着核心角色。


http://www.ppmy.cn/news/1525775.html

相关文章

SMA2:代码实现详解——Image Encoder篇(Hiera章)

SMA2:代码实现详解——Image Encoder篇&#xff08;Hiera&#xff09; 写在前面 大家在SMA2:代码实现详解——Image Encoder篇&#xff08;FpnNeck&#xff09;下的留言我已收到&#xff0c;感谢大家的支持&#xff0c;后面如果遇到比较难以讲清的部分可能会使用视频的形式。…

Unity3D类似于桌面精灵的功能实现

前言&#xff1a; 由于最近在做游戏魔改&#xff0c;很多功能在游戏里面没法实现&#xff08;没错&#xff0c;说的就是排行榜&#xff09;&#xff0c;所以准备用Unity3D开发一个类似于桌面精灵的功能部件&#xff0c;实现效果如下&#xff1a; PS&#xff1a;有需要定制的老…

什么是 Grafana?

什么是 Grafana&#xff1f; Grafana 是一个功能强大的开源平台&#xff0c;用于创建、查看、查询和分析来自多个来源的数据。通过可视化仪表盘&#xff08;Dashboard&#xff09;&#xff0c;它能够帮助用户监控实时数据、生成历史报告&#xff0c;甚至进行预测分析。Grafana…

JVM四种垃圾回收算法以及G1垃圾回收器(面试)

JVM 垃圾回收算法 标记清除算法&#xff1a;标记清除算法将垃圾回收分为两个阶段&#xff1a;标记阶段和清除阶段。 在标记阶段通过根节点&#xff0c;标记所有从根节点开始的对象。然后&#xff0c;在清除阶段&#xff0c;清除所有未被标记的对象 适用场合&#xff1a; 存活对…

Linux面试题3

1. 描述Linux操作系统的安装过程。 以下是关于Linux操作系统的安装过程的描述&#xff1a; 选择发行版&#xff1a;首先&#xff0c;您需要选择一个Linux发行版&#xff0c;如Ubuntu、Fedora、Debian等。不同的发行版有不同的特点和适用场景&#xff0c;您可以根据自己的需求…

【物联网技术大作业】设计一个智能家居的应用场景

前言&#xff1a; 本人的物联网技术的期末大作业&#xff0c;希望对你有帮助。 目录 大作业设计题 &#xff08;1&#xff09;智能家居的概述。 &#xff08;2&#xff09;介绍智能家居应用。要求至少5个方面的应用&#xff0c;包括每个应用所采用的设备&#xff0c;性能&am…

Excel--不规则隔行填充底纹颜色

巧用条件格式快速给小计和总计行填充不同颜色。 先选择整个表格&#xff08;选中第一行&#xff0c;按住Shift双击边框即可选中整个表格&#xff09; 新建条件格式-使用公式确定要设置格式的单元格&#xff0c;输入$B3"小计&#xff1a;"&#xff0c;设置格式&…

【Python 数据分析学习】Pandas的基础和应用(2)

题目 1 数据运算与分析1.1 算数和比较运算1.1.1 算数运算1.1.2 比较运算 1.2 数据排列1.3 统计分析1.3.1 基本的统计分析函数1.3.2 特殊的统计分析函数1.3.3 检查和处理空值 1.4 分组与聚合1.4.1 数据分组1.4.2 数据聚合 1.5 透视交叉表1.5.1 透视表1.5.2 交叉表 2 实战演练2.1…

一个用于翻译 CSV 文件的 Python 脚本,适用于将英文内容批量翻译成中文(或其他语言),并解决文件编码导致的中文乱码和无法翻译的问题。

将CSV文件中的英文批量翻译成中文的 Python 脚本 一个用于翻译 CSV 文件的 Python 脚本&#xff0c;适用于将英文内容批量翻译成中文&#xff08;或其他语言&#xff09;&#xff0c;并解决文件编码导致的中文乱码和无法翻译的问题。 主要功能&#xff1a; 文件编码转换&…

Redis——初识Redis

初识Redis Redis认识Redis 分布式系统单机架构为什么要引入分布式理解负载均衡数据库的读写分离引入主从数据库 引入缓存数据库分库分表业务拆分——微服务常见概念了解 Redis背景介绍特性应用场景Redis不能做的事情Redis客户端redis客户端的多种形态 Redis 认识Redis 存储数…

定时中断键盘灯闪烁

在学习完《趣味定时器》后,是不是只在 dmesg 里看到效果很没劲,这次来点更实际的,我们让键盘灯闪起来。 对于定时器,就不多说了,接下来了解下键盘的基本内容。键盘在 Linux 里是属于TTY(TeleTYpe)设备,既然我们要用到键盘,那先找其通用驱动代码,在 Linux Kernel 源码d…

golang学习笔记14——golang性能问题的处理方法

推荐学习文档 基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&…

玩转扩展库,温湿度传感器篇!—合宙Air201资产定位模组LuatOS快速入门05

随着LuatOS快速入门系列教程的推出&#xff0c;小伙伴们学习热情高涨。 合宙Air201不仅支持三种定位方式&#xff0c;还具有丰富的扩展功能&#xff0c;通过外扩BTB链接方案&#xff0c;最多可支持21个IO接口&#xff1a;SPI、I2C、UART等多种接口全部支持。 本期&#xff0c…

基于python+django+mysql+Nanodet检测模型的水稻虫害检测系统

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

【机器学习(六)】分类和回归任务-LightGBM算法-Sentosa_DSML社区版

文章目录 一、算法概念二、算法原理&#xff08;一&#xff09;Histogram&#xff08;二&#xff09;GOSS1、信息增益2、近似误差 &#xff08;三&#xff09;EFB 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、LightGBM分类任务实现对比&a…

Linux sh命令

目录 一. 基本语法二. 选项2.1 -c 字符串中读取内容&#xff0c;并执行2.1.1 基本用法2.1.2 获取当前目录下失效的超链接 2.2 -x 每个命令执行之前&#xff0c;将其打印出来2.3 结合Here文档使用 一. 基本语法 ⏹Linux 和 Unix 系统中用于执行 shell 脚本 或 运行命令 的命令。…

LabVIEW编程快速提升的关键技术

在LabVIEW程序员的成长道路上&#xff0c;以下几个概念和技术的掌握可以显著提升自我能力&#xff1a; 模块化编程&#xff1a;学会将程序分解成小而独立的模块&#xff08;如子VI&#xff09;&#xff0c;提高程序的可读性、可维护性和可扩展性。这种方式不仅能帮助快速定位问…

Qt使用UDP进行单波通信

Qt使用UDP进行单波通信 我们一般学习完基础的一些编程之后就会开始接触网络编程&#xff0c;我们熟悉的网络编程一般会涉及到两个协议一个时TCP&#xff0c;一个是UDP。TCP一般是point to point&#xff0c;UDP一般有单播和广播两种方式&#xff0c;那么我们今天就来学习一下单…

MFC之CString类及其成员函数用法详解

CString是 CStringT(属于MFC 和 ATL 之间共享的类) 的类模板的专用化&#xff0c;没有基类。在头文件atlstr.h中可以看到CString的定义&#xff1a; CString对象由可变长度的一队字符组成。CString是基于TCHAR数据类型的对象。如果在你的程序中定义了符号_UNICODE&#xff0c;则…

软件测试工程师面试整理-白盒测试

白盒测试(White Box Testing)是一种软件测试方法,在这种方法中,测试人员需要了解和使用软件的内部结构、代码逻辑、算法和实现细节。白盒测试的目标是通过对代码的详细分析来确保每个路径、分支、条件和循环都能够正确执行,从而发现程序中的潜在问题。 1. 白盒测试的特点 …