- 定义:将抽象部分与它的具体实现部分分离,使它们都可以独立的变化,通过组合的方式建立两个类之间的联系,而不是继承
- 类型:结构型
- 适用场景:
- 抽象和具体实现之间增加更多的灵活性
- 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
- 不希望使用继承,或因为多层继承导致系统类的个数剧增
- 优点:
- 分离抽象部分及其具体实现部分
- 提高了系统的可扩展性
- 符合开闭原则
- 符合合成复用原则
- 缺点:
- 增加了系统的理解与设计难度
- 需要正确的识别出系统中两个独立变化的维度
- 相关设计模式:
- 桥接模式和组合模式:组合模式强调的是部分和整体间的组合,而桥接模式强调的是平行级别上不同类的组合
- 桥接模式和适配器模式:都是让两个东西配合工作,两个模式的目的又不一样,适配器是改变已有的接口,让它们之间可以相互配合,而桥接模式是分离抽象和具体的实现,目的是分离
coding(各驱动之间设计)
实现层
/** * <p>数据库驱动接口</p> */ public interface IDriver { /** * 连接 */ void connect(); } /** * <p>MySql数据库驱动类</p> */ public class MySqlDriver implements IDriver { private String url; private String user; private String pwd; public MySqlDriver(String url, String user, String pwd) { this.url = url; this.user = user; this.pwd = pwd; } @Override public void connect() { System.out.println("url:" + this.url); System.out.println("user:" + this.user); System.out.println("pwd:" + this.pwd); System.out.println("mysql驱动连接数据库"); } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } } /** * <p>Oracle数据库驱动类</p> */ public class OracleDriver implements IDriver { @Override public void connect() { System.out.println("oracle驱动连接数据库"); } } /** * <p>PostGreSql数据库驱动类</p> */ public class PostgreSqlDriver implements IDriver { @Override public void connect() { System.out.println("postgresql驱动连接数据库"); } }
抽象层
/** * <p>各驱动之间的桥梁</p> * */ public abstract class AbstractBridge { // 聚合和关联驱动接口实例 private IDriver driver; public IDriver getDriver() { return driver; } public void setDriver(IDriver driver) { this.driver = driver; } public abstract void connect(); } /** * <p>驱动管理器 == 实现不同驱动设备之间的数据库连接</p> * */ public class DriverManager extends AbstractBridge { @Override public void connect() { getDriver().connect(); } }
UML
coding(绘制图案)
实现层
/** * <p>颜色接口</p> * */ public interface Color { void painting(String shape); } /** * <p>绿色</p> * */ public class Green implements Color { @Override public void painting(String shape) { System.out.println("绘制绿色的" + shape); } } /** * <p>红色</p> * */ public class Red implements Color { @Override public void painting(String shape) { System.out.println("绘制红色的" + shape); } } /** * <p>白色</p> * */ public class White implements Color { @Override public void painting(String shape) { System.out.println("绘制白色的" + shape); } }
抽象层
/** * <p>抽象形状类 -- 聚合与关联Color实现类</p> * */ public abstract class AbstractShape { private Color color; public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } /** * 抽象方法 == 绘制图案 */ abstract void draw(); } /** * <p>圆形</p> * */ public class Circle extends AbstractShape { @Override public void draw() { getColor().painting("圆形"); } } /** * <p>矩形、长方形</p> * */ public class Rectangle extends AbstractShape { @Override public void draw() { getColor().painting("矩形"); } } /** * <p>正方形</p> * */ public class Square extends AbstractShape { @Override public void draw() { getColor().painting("正方形"); } }
UML
测试
/** * <p>桥接模式测试</p> * */ public class BridgeTest { public static void main(String[] args) { driverConnect(); drawShape(); /** * 1、分离抽象接口及其实现部分。提高了比继承更好的解决方案 * 2、桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统 * 3、对客户隐藏实现细节 */ } /** * 不同驱动连接数据库 */ private static void driverConnect() { DriverManager driverManager = new DriverManager(); String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true"; String user = "root"; String pwd = "root"; // mysql驱动连接数据库 IDriver mySqlDriver = new MySqlDriver(url, user, pwd); driverManager.setDriver(mySqlDriver); driverManager.connect(); System.out.println("========= 分割线 ========="); // oracle驱动连接数据库 IDriver oracleDriver = new OracleDriver(); driverManager.setDriver(oracleDriver); driverManager.connect(); System.out.println("\n========= 分割线 =========\n"); } /** * 绘制不同颜色的形状 */ private static void drawShape() { //绘制红色的矩形 Color red = new Red(); Rectangle rectangle = new Rectangle(); rectangle.setColor(red); rectangle.draw(); //绘制绿色的正方形 Color green = new Green(); Square square = new Square(); square.setColor(green); square.draw(); //绘制白色的圆形 Color white = new White(); Circle circle = new Circle(); circle.setColor(white); circle.draw(); } } ========结果========= url:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true user:root pwd:root mysql驱动连接数据库 ========= 分割线 ========= oracle驱动连接数据库 ========= 分割线 ========= 绘制红色的矩形 绘制绿色的正方形 绘制白色的圆形
coding((各个)银行和(活期、定期)账户的设计)
实现层
账户接口和活期定期账户
public interface Account { Account openAccount(); void showAccountType(); } public class DepositAccount implements Account { @Override public Account openAccount() { System.out.println("打开定期账号"); return new DepositAccount(); } @Override public void showAccountType() { System.out.println("这是一个定期账号(委托给实现处理)"); } } public class SavingAccount implements Account { @Override public Account openAccount() { System.out.println("打开活期账号"); // ... return new SavingAccount(); } @Override public void showAccountType() { System.out.println("这是一个活期账号(委托给实现处理)"); } }
抽象层
银行抽象类和ABC、ICBC银行
public abstract class Bank { protected Account account; public Bank(Account account){ this.account = account; } abstract Account openAccount(); } public class ABCBank extends Bank { public ABCBank(Account account) { super(account); } @Override Account openAccount() { System.out.println("打开中国农业银行账号"); account.openAccount(); // 这是重点 return account; } } public class ICBCBank extends Bank { public ICBCBank(Account account) { super(account); } @Override Account openAccount() { System.out.println("打开中国工商银行账号"); account.openAccount(); // 这是重点 return account; } }
UML
可以看到,UML类图左侧是实现层,右侧是抽象层,所以桥接模式最重要的是把桥的两侧划分清楚,Account可以理解为桥的实现接口,下面两个是其具体实现类,然后右边是Bank抽象类,注意它通过组合的方式使用了左侧Account接口,这就是桥接模式的核心。通过桥接模式,把实现部分(左侧)和抽象部分(右侧)进行一个桥接,通过组合方式结合合成复用原则来达到抽象层和实现层分离,并且各自可以独立发展,如果要加一个银行,在右侧抽象层继承抽象类即可,要加一个账号,在左侧实现接口即可。
测试
public class Test { public static void main(String[] args) { Bank icbcBank = new ICBCBank(new DepositAccount()); Account icbcAccount = icbcBank.openAccount(); icbcAccount.showAccountType(); Bank icbcBank2 = new ICBCBank(new SavingAccount()); Account icbcAccount2 = icbcBank2.openAccount(); icbcAccount2.showAccountType(); Bank abcBank = new ABCBank(new SavingAccount()); Account abcAccount = abcBank.openAccount(); abcAccount.showAccountType(); } } ======结果===== 打开中国工商银行账号 打开定期账号(委托给实现处理) 这是一个定期账号 打开中国工商银行账号 打开活期账号(委托给实现处理) 这是一个活期账号 打开中国农业银行账号 打开活期账号(委托给实现处理) 这是一个活期账号
注意:
还有个要注意的点在于,银行具体的实现类方法 openAccount() 里面,不要所有的实现都自己完成,而是要委托给account去实现,因为只有通过具体的委托,以后account里边的 openAccount() 无论如何扩展的话,Bank里面的 openAccount() 是不用动的,不要把实现挪到抽象的里面,要把具体的行为委托出去。
源码中的应用
- java.sql.Driver:Java数据库驱动,mysql的jdbc实现了Driver,如果添加了oracle,那么oracle的jdbc也会实现Driver,那它们是如何获取连接的呢,可以打开以下这个类
- java.sql.DriverManager:DriverManager 类有个DriverInfo 列表,其实它就是对Driver的具体封装,DriverManager类有个registerDriver方法,把Driver注册进来,驱动注册完之后,可以看看它里面getConnection方法,通过这个静态方法获取具体的连接,于是jdbc通过DriverManager,对外提供了操作数据库的统一接口,通过这个方法可以获取不同的数据库连接,并且通过返回值Connection里边提供了具体方法来对数据库进行操作,那jdbc为不同的数据库提供了相同的操作方法,无论是操作mysql还是操作oracle里面的方法是一样的。
public class DriverManager { ... // List of registered JDBC drivers private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); ... public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) throws SQLException { /* Register the driver if it has not already been added to our list */ if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); } else { // This is for compatibility with the original DriverManager throw new NullPointerException(); } println("registerDriver: " + driver); } 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())); } } class DriverInfo { final Driver driver; DriverAction da; DriverInfo(Driver driver, DriverAction action) { this.driver = driver; da = action; } }
标签:Account,String,桥接,void,模式,class,new,public From: https://www.cnblogs.com/wangzhilei-src/p/17976756