结构型-桥接模式

定义

将抽象部分与它的具体实现部分分离,使他们都可以独立的变化。
通过组合的方式建立两个类之间的联系,而不是继承。

类型

结构型

适用场景

  • 抽象和具体实现之间增加更多的灵活性
  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展
  • 不希望使用继承,或因为多层继承导致系统类的个数剧增

优点

  • 分离抽象部分及其具体实现部分(大白话就是抽象和实现之间不再是继承关系)
  • 提供了系统的可扩展性
  • 符合开闭原则
  • 符合合成复用原则

缺点

  • 增加了系统的理解和设计难度
    因为类和类的关系增加了抽象层,这就要求我们在设计时候就要针对抽象层进行设计
  • 需要正确地识别出系统中两个独立变化的维度
    适用范围还是有局限性,需要根据业务场景,正确使用也需要一定的经验积累

相关设计模式

  • 桥接模式和组合模式
    组合模式强调的是树形结构上的组合;桥接模式强调的是平行上的组合
  • 桥接模式和适配器模式
    共同点都是为了让两个东西配合工作;目的不一样,适配器是改变业务的接口,让它们可以相互配合,而桥接模式是分离抽象和具体实现,就是为了分离。

Coding

业务场景:
中国有很多银行,中国银行、建设银行等等。
我们的账号又分为两种:活期和定期。

/**
 * 账号
 */
public interface Account {
    Account openAccount();
    void showAccountType();
}
/**
 * 定期账号
 **/
public class DepositAccount implements Account{

    @Override
    public Account openAccount() {
        System.out.println("打开定期账号");
        return new SavingAccount();
    }

    @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("这是一个活期账号");
    }
}
/**
 * 银行
 **/
public abstract class Bank {
    protected Account account;
    public Bank(Account account){
        this.account=account;
    }
    abstract Account openAccount();
}
public class ICBCBank extends Bank {
    public ICBCBank(Account account){
        super(account);
    }
    @Override
    Account openAccount() {
        System.out.println("打开工商银行账号");
        account.openAccount();
        return account;
    }
}
public class ABCBank extends Bank{
    public ABCBank(Account account){
        super(account);
    }
    @Override
    Account openAccount() {
        System.out.println("打开中国农业银行账号");
        account.openAccount();
        return account;
    }
}

UML类图
在这里插入图片描述
红色的线就是Bank和Account之间的桥。Bank的打开账号行为是抽象的,不同的银行打开的行为不一样。Account的打开账号的行为是相对固定的,把Account的实现和Bank的抽象组合起来,就是这条线。

如果不使用桥接,每个银行下面定义定期、活期两个类,那银行多了,账户类也就多了,会造成类泛滥。但这样桥接后,就可以减少类的定义,这也正是桥接模式的净化所在。

我们再写下应用类

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();
    }
}

运行结果

打开工商银行账号
打开定期账号
这是一个定期账号
打开工商银行账号
打开活期账号
这是一个活期账号
打开中国农业银行账号
打开活期账号
这是一个活期账号

注意:千万不要忘记Account委托给Bank的openAccunt行为要在Bank实现类中调用,不然不符合迪米特原则(类之间的解耦)

源码解析

在这里插入图片描述

我们看下Java的java.sql.Driver的实现类,com.mysql.jdbc.Driver实现类Driver,那如果我们的项目添加了Oracle的驱动、SqlServer的驱动的话,可以看到这些驱动,都实现了java.sql.Driver接口,那具体的MySql中的Driver、Oracle中的Driver就是桥接模式中的实现部分。那Jdbc如何获取数据库的链接呢?
在这里插入图片描述
我们看DriverManager,我们看到有个CopyOnWriteArrayList类型的属性,类型的元素是DriverInfo(具体的驱动信息),我们看一下这个类型里面是如何封装的
在这里插入图片描述
看到它是对Driver的具体封装。我们再回来看CopyOnWriteArrayList类型的属性所在的类DriverManager,它里面主要的方法就是registerDriver
在这里插入图片描述
我们知道,通过Class.forName(com.mysql.jdbc.Driver)加载驱动,我们看下mysql的Driver类
在这里插入图片描述
当执行Class.forName方法时,我们会直接调用static静态块,静态块中又回到了DriverMananger的registerDriver方法
在这里插入图片描述
注册进来后,就把new Driver赋值给了registeredDriver属性在这里插入图片描述
我们接下来,再看getConnection方法,
在这里插入图片描述
我们平时用的最多的就是三个string类型参数的方法,
在这里插入图片描述
三个参数要传链接、用户名、密码,通过这个方法来获取数据库连接,或者说jdbc通过DriverManager对外提供了操作数据库的统一接口getConnetion,方法返回的是Connection,我们可以通过它的方法操作连接,那再看下Connection
在这里插入图片描述
里面方法是执行各种sql的方法,这是为不同数据库提供的相同的接口,也就是里面的各种方法,无论是操作MySql还是Oracle,里面的方法是一样的,不同的是,我们看下实现类
在这里插入图片描述
第一个是Mysql的Connection接口,第二个是mySql的Connection实现类,当然如果我们的项目pom总有oracle的驱动,就也能找到oracle的实现了jdbc的Connection接口的具体实现类,也就是针对不同数据库,通过DriverManager里的getConnection方法,获取的都是相同的Connection接口,也就是说jdbc在最初设计的时候,设计了接口,再由各个数据库公司自己来实现这个接口 ,我们在调用的过程中,只需要使用接口就可以了。

这就是桥接模式在jdbc中的使用,看到很好实现了开闭原则,无论是有什么数据库厂商,只要具体实现了jdbc这些接口的话,都可以加入到java的数据库操作中。

在这里插入图片描述
DriverManager中的DriverInfo封装了Driver,我们可以看成它就是Driver,所以DriverManager和Driver之间就实现了桥接模式,而Driver呢,还有mysql.Driver、Oracle的Driver等具体的Driver实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值