设计模式笔记:桥接模式如何应用于实际案例?

2026-05-19 17:311阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1872个文字,预计阅读时间需要8分钟。

设计模式笔记:桥接模式如何应用于实际案例?

桥接(Bridge)模式将抽象部分与实现部分分离,使得它们都可以独立地变化。一、桥接模式介绍我们知道,抽象部分一般是指接口或抽象类,实现部分是指具体实现这些接口或抽象类的类。桥接模式通过将这两者分离,使得它们之间解耦,从而实现更灵活的设计。

二、桥接模式应用在桥接模式中,抽象部分和实现部分通常通过接口或抽象类连接。它们之间主要有两种连接方式:继承和实现。

设计模式笔记:桥接模式如何应用于实际案例?

1. 继承通过继承关系,抽象部分可以继承实现部分的具体实现。这种方式适用于实现部分的变化较少,且与抽象部分关系较为紧密的情况。

2. 实现通过实现关系,抽象部分直接实现实现部分的具体方法。这种方式适用于实现部分的变化较多,且与抽象部分关系较为松散的情况。

三、总结桥接模式通过分离抽象部分和实现部分,使得它们可以独立变化,从而提高系统的灵活性和可扩展性。在实际应用中,根据具体需求选择合适的连接方式,以达到最佳的设计效果。

桥接(Bridge)模式是指将抽象部分与实现部分相分离,使它们都可以独立的发生变化。

一、桥接模式介绍

我们知道,抽象部分一般与实现部分连接有两种方式:继承和实现。那么如何将其解耦分离,桥接模式提供一种方式,也就是将强关联转为弱关联,将继承转换为组合关系。如下图所示,取消两者的继承关系,改用组合关系:

1.1 桥接模式的结构

我们可以看看桥接模式是怎么解耦,利用组合连接抽象和实现部分,如下所示:

其结构中包含如下角色:

  • Abstraction:抽象化角色,定义抽象类,包含一个对实现化对象的引用(组合)
  • RefinedAbstraction:扩展抽象化角色,实现抽象化角色的子类,由此通过组合关系调用实现化角色中的业务方法
  • Implementor:实现化角色的接口,供扩展抽象化角色调用
  • ImplementorA、ImplementorB:实现化角色的具体实现
1.2 桥接模式的实现

我们可以根据上面的UML图实现对应的代码:

//客户端类 public class Client { public static void main(String[] args) { Implementor imple = new ImplementorA(); Abstraction abs = new RefinedAbstraction(imple); abs.Operation(); } } //实现化角色 interface Implementor { public void OperationImpl(); } //具体的实现化角色 class ImplementorA implements Implementor { public void OperationImpl() { System.out.println("我是具体实现化角色A"); } } class ImplementorB implements Implementor { public void OperationImpl() { System.out.println("我是具体实现化角色B"); } } //抽象化角色 abstract class Abstraction { protected Implementor imple; protected Abstraction(Implementor imple) { this.imple = imple; } public abstract void Operation(); } //扩展抽象化角色 class RefinedAbstraction extends Abstraction { protected RefinedAbstraction(Implementor imple) { super(imple); } public void Operation() { System.out.println("扩展抽象化角色被访问"); imple.OperationImpl(); } }

实现结果:

扩展抽象化角色被访问 我是具体实现化角色A 二、桥接模式的应用场景 2.1 JDBC 驱动器

JDBC为所有的关系型数据库提供一个通用的标准,这就是一个桥接模式的典型应用。我们先回顾一下JDBC的使用,用JDBC连接MySQL数据库主要分为这样几步:

//1.加载MySQL驱动注入到DriverManager Class.forName("com.mysql.cj.jdbc.Driver"); //2.提供JDBC连接的URL、用户名和密码 String url = "jdbc:mysql://localhost:3306/test_db?"; String username = "root"; String password = "root"; //3.创建数据库的连接 Connection connection = DriverManager.getConnection(url, username, password); //4.创建statement实例 Statement statement = connection.createStatement(); //5.执行SQL语句 String query = "select * from test"; //查询语句,也可以换成CRUD的其他语句 ResultSet resultSet = statement.executeQuery(query); //6.关闭连接对象 connection.close();

我们一步步来看,先看步骤1:

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

查看对应的 com.mysql.cj.jdbc.Driver路径下的源码:

package com.mysql.cj.jdbc; import java.sql.DriverManager; import java.sql.SQLException; public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }

是通过静态方法调用registerDriver()方法来将MySQL驱动注入到DriverManagerregisterDriver()方法具体如下:

public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { //直接调用下面的同名静态方法 registerDriver(driver, null); } public static synchronized void registerDriver(java.sql.Driver driver,DriverAction da)throws SQLException { /* registeredDrivers是一个list,用DriverInfo实例封装Driver */ 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:

public class DriverManager { // List of registered JDBC drivers private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); //... }

DriverInfo类中封装了java.sql.Driver接口:

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

再看步骤2、3,重点是步骤3

Connection connection = DriverManager.getConnection(url, username, password);

Connection接口是和特定数据库的连接会话,不同的数据库的连接会话都不相同:

public interface Connection extends Wrapper, AutoCloseable { Statement createStatement() throws SQLException; //... }

是通过DriverManager中的getConnection方法,从registeredDrivers进行选择对应数据库驱动下的连接实例:

public static Connection getConnection(String url,String user, String password) throws SQLException { java.util.Properties info = new java.util.Properties(); if (user != null) { info.put("user", user); } if (password != null) { info.put("password", password); } return (getConnection(url, info, Reflection.getCallerClass())); } // 实际上调用的是下面的静态方法getConnection // Worker method called by the public getConnection() methods. private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } println("DriverManager.getConnection(\"" + url + "\")"); // Walk through the loaded registeredDrivers attempting to make a connection. // Remember the first exception that gets raised so we can reraise it. SQLException reason = null; 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()); } } // if we got here nobody could connect. if (reason != null) { println("getConnection failed: " + reason); throw reason; } println("getConnection: no suitable driver found for "+ url); throw new SQLException("No suitable driver found for "+ url, "08001"); }

Connection接口的具体实现部分,MySQL的连接是通过两层实现完成抽象部分的实现:

public class ConnectionImpl implements JdbcConnection, SessionEventListener, Serializable { private static final long serialVersionUID = 4009476458425101761L; private static final SQLPermission SET_NETWORK_TIMEOUT_PERM = new SQLPermission("setNetworkTimeout"); //... } public interface JdbcConnection extends Connection, MysqlConnection, TransactionEventHandler { JdbcPropertySet getPropertySet(); void changeUser(String var1, String var2) throws SQLException; //... }

综上我们可以画出对应的类图:

参考资料

c.biancheng.net/view/1364.html

jishuin.proginn.com/p/763bfbd68968

www.cnblogs.com/kuluo/p/13038076.html

本文共计1872个文字,预计阅读时间需要8分钟。

设计模式笔记:桥接模式如何应用于实际案例?

桥接(Bridge)模式将抽象部分与实现部分分离,使得它们都可以独立地变化。一、桥接模式介绍我们知道,抽象部分一般是指接口或抽象类,实现部分是指具体实现这些接口或抽象类的类。桥接模式通过将这两者分离,使得它们之间解耦,从而实现更灵活的设计。

二、桥接模式应用在桥接模式中,抽象部分和实现部分通常通过接口或抽象类连接。它们之间主要有两种连接方式:继承和实现。

设计模式笔记:桥接模式如何应用于实际案例?

1. 继承通过继承关系,抽象部分可以继承实现部分的具体实现。这种方式适用于实现部分的变化较少,且与抽象部分关系较为紧密的情况。

2. 实现通过实现关系,抽象部分直接实现实现部分的具体方法。这种方式适用于实现部分的变化较多,且与抽象部分关系较为松散的情况。

三、总结桥接模式通过分离抽象部分和实现部分,使得它们可以独立变化,从而提高系统的灵活性和可扩展性。在实际应用中,根据具体需求选择合适的连接方式,以达到最佳的设计效果。

桥接(Bridge)模式是指将抽象部分与实现部分相分离,使它们都可以独立的发生变化。

一、桥接模式介绍

我们知道,抽象部分一般与实现部分连接有两种方式:继承和实现。那么如何将其解耦分离,桥接模式提供一种方式,也就是将强关联转为弱关联,将继承转换为组合关系。如下图所示,取消两者的继承关系,改用组合关系:

1.1 桥接模式的结构

我们可以看看桥接模式是怎么解耦,利用组合连接抽象和实现部分,如下所示:

其结构中包含如下角色:

  • Abstraction:抽象化角色,定义抽象类,包含一个对实现化对象的引用(组合)
  • RefinedAbstraction:扩展抽象化角色,实现抽象化角色的子类,由此通过组合关系调用实现化角色中的业务方法
  • Implementor:实现化角色的接口,供扩展抽象化角色调用
  • ImplementorA、ImplementorB:实现化角色的具体实现
1.2 桥接模式的实现

我们可以根据上面的UML图实现对应的代码:

//客户端类 public class Client { public static void main(String[] args) { Implementor imple = new ImplementorA(); Abstraction abs = new RefinedAbstraction(imple); abs.Operation(); } } //实现化角色 interface Implementor { public void OperationImpl(); } //具体的实现化角色 class ImplementorA implements Implementor { public void OperationImpl() { System.out.println("我是具体实现化角色A"); } } class ImplementorB implements Implementor { public void OperationImpl() { System.out.println("我是具体实现化角色B"); } } //抽象化角色 abstract class Abstraction { protected Implementor imple; protected Abstraction(Implementor imple) { this.imple = imple; } public abstract void Operation(); } //扩展抽象化角色 class RefinedAbstraction extends Abstraction { protected RefinedAbstraction(Implementor imple) { super(imple); } public void Operation() { System.out.println("扩展抽象化角色被访问"); imple.OperationImpl(); } }

实现结果:

扩展抽象化角色被访问 我是具体实现化角色A 二、桥接模式的应用场景 2.1 JDBC 驱动器

JDBC为所有的关系型数据库提供一个通用的标准,这就是一个桥接模式的典型应用。我们先回顾一下JDBC的使用,用JDBC连接MySQL数据库主要分为这样几步:

//1.加载MySQL驱动注入到DriverManager Class.forName("com.mysql.cj.jdbc.Driver"); //2.提供JDBC连接的URL、用户名和密码 String url = "jdbc:mysql://localhost:3306/test_db?"; String username = "root"; String password = "root"; //3.创建数据库的连接 Connection connection = DriverManager.getConnection(url, username, password); //4.创建statement实例 Statement statement = connection.createStatement(); //5.执行SQL语句 String query = "select * from test"; //查询语句,也可以换成CRUD的其他语句 ResultSet resultSet = statement.executeQuery(query); //6.关闭连接对象 connection.close();

我们一步步来看,先看步骤1:

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

查看对应的 com.mysql.cj.jdbc.Driver路径下的源码:

package com.mysql.cj.jdbc; import java.sql.DriverManager; import java.sql.SQLException; public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }

是通过静态方法调用registerDriver()方法来将MySQL驱动注入到DriverManagerregisterDriver()方法具体如下:

public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { //直接调用下面的同名静态方法 registerDriver(driver, null); } public static synchronized void registerDriver(java.sql.Driver driver,DriverAction da)throws SQLException { /* registeredDrivers是一个list,用DriverInfo实例封装Driver */ 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:

public class DriverManager { // List of registered JDBC drivers private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); //... }

DriverInfo类中封装了java.sql.Driver接口:

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

再看步骤2、3,重点是步骤3

Connection connection = DriverManager.getConnection(url, username, password);

Connection接口是和特定数据库的连接会话,不同的数据库的连接会话都不相同:

public interface Connection extends Wrapper, AutoCloseable { Statement createStatement() throws SQLException; //... }

是通过DriverManager中的getConnection方法,从registeredDrivers进行选择对应数据库驱动下的连接实例:

public static Connection getConnection(String url,String user, String password) throws SQLException { java.util.Properties info = new java.util.Properties(); if (user != null) { info.put("user", user); } if (password != null) { info.put("password", password); } return (getConnection(url, info, Reflection.getCallerClass())); } // 实际上调用的是下面的静态方法getConnection // Worker method called by the public getConnection() methods. private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } println("DriverManager.getConnection(\"" + url + "\")"); // Walk through the loaded registeredDrivers attempting to make a connection. // Remember the first exception that gets raised so we can reraise it. SQLException reason = null; 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()); } } // if we got here nobody could connect. if (reason != null) { println("getConnection failed: " + reason); throw reason; } println("getConnection: no suitable driver found for "+ url); throw new SQLException("No suitable driver found for "+ url, "08001"); }

Connection接口的具体实现部分,MySQL的连接是通过两层实现完成抽象部分的实现:

public class ConnectionImpl implements JdbcConnection, SessionEventListener, Serializable { private static final long serialVersionUID = 4009476458425101761L; private static final SQLPermission SET_NETWORK_TIMEOUT_PERM = new SQLPermission("setNetworkTimeout"); //... } public interface JdbcConnection extends Connection, MysqlConnection, TransactionEventHandler { JdbcPropertySet getPropertySet(); void changeUser(String var1, String var2) throws SQLException; //... }

综上我们可以画出对应的类图:

参考资料

c.biancheng.net/view/1364.html

jishuin.proginn.com/p/763bfbd68968

www.cnblogs.com/kuluo/p/13038076.html