一、桥接模式介绍
1、定义与类型
定义:将抽象部分与它的具体实现部分分离,使它们都可以独立地变化
通过组合的方式建立两个类之间联系,而不是继承
类型:结构型
2、适用场景
抽象和具体实现之间增加更多的灵活性
一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
不希望使用继承,或因为多层继承导致系统类的个数剧增
3、优点
分离抽象部分及其具体实现部分
提高了系统的可扩展性
符合开闭原则
符合合成复用原则
4、缺点
增加了系统的理解与设计难度
需要正确地识别出系统中两个独立变化的维度
5、相关设计模式
桥接模式和组合模式
组合模式强调部分和整体的组合,桥接模式强调平行级别上不同类的组合
桥接模式和适配器模式
共同点:都是为了让两个东西共同工作
适配器:为了改变已有的接口,以达到相互配合
桥接模式:分离抽象和具体的实现,目的是为了分离
二、代码示例
模拟银行账号业务:
银行账号有:定期账号、活期账号等等
银行有:工商银行、农业银行、建设银行等等
如果每个银行的每种账号类型都创建一个类,即:工商银行定期账号、工商银行活期账号、农业银行定期账号、农业银行活期账号、建设银行定期账号、建设银行活期账号..... 那类将会越来越多,即会发生类爆炸
如果使用桥接模式,将银行账号类和银行类组合起来,即可避免类爆炸,也符合开闭原则、合成复用原则,以后如果有新的账号类型,直接实现账号接口即可;如果有新的银行出现,直接继承银行抽象类即可。
银行账号接口:
public interface Account {
Account openAccount();
void showAccountType();
}
活期银行账号类:
public class SavingAccount implements Account {
@Override
public Account openAccount() {
System.out.println("打开活期账号");
//...
return new SavingAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个活期账号");
}
}
定期银行账号类:
public class DepositAccount implements Account {
@Override
public Account openAccount() {
System.out.println("打开定期账号");
return new DepositAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个定期账号");
}
}
银行抽象类:
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;
}
}
测试类:
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();
}
}
输出:
打开中国工商银行账号
打开定期账号
这是一个定期账号
打开中国工商银行账号
打开活期账号
这是一个活期账号
打开中国农业银行账号
打开活期账号
这是一个活期账号
三、源码示例
JDK中的Driver、DriverManager
各个数据库会实现具体的实现类,体现了开闭原则,不论会新出现什么数据库,只要实现了具体类,即可通过Class.forName进行调用