标签:ret new 一个 不同的 类图 oid saving 不可 开发工程师
《设计模式自习室》系列,顾名思义,本系列文章带你温习常见的设计模式。主要内容有:
该系列会逐步更新于我的博客和公众号(博客见文章底部),也希望各位观众老爷能够关注我的个人公众号:后端技术漫谈,不会错过精彩好看的文章。
桥接模式是软件设计模式中最复杂的模式之一,它把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。
如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
就拿汽车在路上行驶的来说。即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,然而它们所行驶的环境(路)也在变化,在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢?
将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
如果看不懂UML类图,可以先粗略浏览下该图,想深入了解的话,可以继续谷歌,深入学习:
桥接模式类图:
时序图(Sequence Diagram)是显示对象之间交互的图,这些对象是按时间顺序排列的。时序图中显示的是参与交互的对象及其对象之间消息交互的顺序。
我们可以大致浏览下时序图,如果感兴趣的小伙伴可以去深究一下:
代码参考:
https://segmentfault.com/a/1190000020107419
我们有不同的银行(工行,农行,建行),也有不同的卡(储蓄卡,信用卡),我们将银行和卡进行抽象。
/**
* 银行抽象类
*/
public abstract class Bank {
protected Account account;
public Bank(Account account) {
this.account = account;
}
/**
* 不限制方法名,但因为委派所以起的一样
* 不要自己都实现了,要尽量把行为委托给组合的类
* @return
*/
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;
}
}
/**
* 银行账号, 桥的实现接口
*/
public interface Account {
/**
* 打开账号
* @return
*/
Account openAccount();
/**
* 查看账号类型
*/
void showAccountType();
}
/**
* 定期账户实现类
*/
public class DepositAccount implements Account {
@Override
public DepositAccount openAccount() {
System.out.println("打开定期账号");
return new DepositAccount();
}
@Override
public void showAccountType() {
System.out.println("这是定期账号");
}
}
/**
* 活期账户实现类
*/
public class SavingAccount implements Account {
@Override
public SavingAccount openAccount() {
System.out.println("打开活期账号");
return new SavingAccount();
}
@Override
public void showAccountType() {
System.out.println("这是活期账号");
}
}
客户端调用:
public class Test {
public static void main(String[] args) {
Bank icbcBank = new ICBCBank(new DepositAccount());
Account icbcAccount = icbcBank.openAccount();
icbcAccount.showAccountType();
Bank abcBank = new ABCBank(new SavingAccount());
Account abcAccount = abcBank.openAccount();
abcAccount.showAccountType();
}
}
调用结果:
打开中国工商银行账号
打开定期账号
这是定期账号
打开中国农业银行账号
打开活期账号
这是活期账号
JDBC数据库访问接口API正是经典的桥接模式实现:
通常使用JDBC连接数据库时,会使用如下代码:
Class.forName("数据库类驱动器");
Connection conn = DriverManager.getConnection("数据库url", "用户名", "密码");
//.................
JDBC为不同的数据库操作提供了相同的接口,但是JDBC本身并没有针对每种数据库提供一套具体实现代码,而是通过接口java.sql.Driver的connect方法连接到了不同的数据库实现。
如连接mysql数据库:
package com.mysql.jdbc;
public class NonRegisteringDriver implements java.sql.Driver //对java.sql.Driver接口提供了实现
{
public Connection connect(String url, Properties info)
throws SQLException
{
//实现
}
//其他方法
}
Java在连接MySQL时需要使用mysql-connector-java.jar,mysql-connector-java.jar包提供了对MySQL数据库操作的具体实现,并通过接口Driver连接到了JDBC统一的api。
详细的JDBC源码分析可以参考:
https://blog.csdn.net/qq_28241149/article/details/78548178
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
这两个模式在一定程度上都是为了减少子类的数目,避免出现复杂的继承关系。但是它们解决的方法却各有不同
共同点:
桥接和适配器都是让两个东西配合工作
不同点:
适配器:改变已有的两个接口,让他们相容。所以说,如果你拿到两个已有模块,想让他们同时工作,那么你使用的适配器。
桥接模式:分离抽象化和实现,使两者的接口可以不同,目的是分离,但是并不修改任何接口的具体内容。如果你还什么都没有,但是想分开实现,那么桥接是一个选择。
我是一名后端开发工程师。
主要关注后端开发,数据安全,爬虫,物联网,边缘计算等方向,欢迎交流。
公众号:后端技术漫谈.jpg
如果文章对你有帮助,不妨收藏,投币,转发,在看起来~
【设计模式自习室】桥接模式 Bridge Pattern:处理多维度变化
标签:ret new 一个 不同的 类图 oid saving 不可 开发工程师
原文地址:https://blog.51cto.com/15047490/2560687