✍ 在介绍桥接模式之前,我们引入一个场景:
设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4 个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:
对于有 两个变化维度 ( 即两个变化的原因 ) 的系统 , 采用 方案二 来进行设计系统中类的个数更少 , 且系统扩展更为方便 。相比方案一是非常好的选择。之所以引出这个简单的例子,是因为设计方案二即是桥接模式的应用 。 桥接模式 将继承关系转换为关联关系
, 从而 降低了类与类之间的耦合 , 减少了代码编写量
给桥接模式下个定义就是:
桥接模式(Bridge Pattern) : 将抽象部分与它的实现部分分离,使它们都可以独立地变化 。
它是一种对象结构型模式,又称为柄体(Handle and Body) 模式或接口(Interface)
桥接模式包含如下角色:
✍ 演示一下:
具体的实现委托给了Account接口(Implementor:实现类接口)
public interface Account {
Account openAccount();
void showAccountType();
}
抽象类Bank (Abstraction:抽象类)
public abstract class Bank {
protected Account account; //只有子类能拿到account
public Bank(Account account){
this.account = account;
}
abstract Account openAccount();
}
定期账号(ConcreteImplementor:具体实现类)
//定期账号
public class DepositAccount implements Account{
@Override
public Account openAccount() {
System.out.println("打开定期账号");
return new DepositAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个定期账号");
}
}
活期账号(ConcreteImplementor:具体实现类)
//活期账号
public class SavingAccount implements Account{
@Override
public Account openAccount() {
System.out.println("打开活期账号");
return new SavingAccount();
}
@Override
public void showAccountType() {
System.out.println("这是一个活期账号");
}
}
ABC银行(RefinedAbstraction:扩充抽象类)
public class ABCBank extends Bank{
public ABCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开ABC银行账号");
account.openAccount();
return account;//account来自父类
}
}
ICBC银行(RefinedAbstraction:扩充抽象类)
public class ICBCBank extends Bank{
public ICBCBank(Account account) {
super(account);
}
@Override
Account openAccount() {
System.out.println("打开ICBC银行账号");
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 abcBank = new ABCBank(new SavingAccount());
Account abcAccount = abcBank.openAccount();
abcAccount.showAccountType();
}
}
✍ 理解桥接模式,重点需要理解如何将 抽象化(Abstraction) 与 实现化(Implementation) 脱耦 ,使得二者可以独立地变化。
✍ 说一下桥接模式的优缺点:
桥接模式的优点
桥接模式的缺点
✍ 在以下情况下可以使用桥接模式:
✍ 桥接模式的应用有很多比如:
一个 Java 桌面软件总是带有所在操作系统的视感(LookAndFeel) ,如果一个Java 软件是在Unix 系统上开发的,那么开发人员看到的是Motif 用户界面的视感;在Windows 上面使用这个系统的用户看到的是Windows 用户界面的视感;而一个在Macintosh 上面使用的用户看到的则是Macintosh 用户界面的视感,Java 语言是通过所谓的Peer 架构做到这一点的。Java为AWT 中的每一个GUI 构件都提供了一个Peer 构件, 在AWT 中的Peer 架构就使用了桥接模式
JDBC 驱动程序也是桥接模式的应用之一。使用JDBC 驱动程序的应用系统就是抽象角色,而所使用的数据库是实现角色。 一个JDBC 驱动程序可以动态地将一个特定类型的数据库与一个Java 应用程序绑定在一起,从而实现抽象角色与实现角色的动态耦合。
✍ 适配器模式与桥接模式的联用
桥接模式和适配器模式用于设计的不同阶段,桥接模式用于系统的初步设计,对于存在两个独立变化维度的类可以将其分为抽象化和实现化两个角色,使它们可以分别进行变化;而在初步设计完成之后,当发现系统与已有类无法协同工作时,可以采用适配器模式。但有时候在设计初期也需要考虑适配器模式,特别是那些涉及到大量第三方应用接口的情况。