桥接模式

一、桥接模式介绍

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进行调用

posted @ 2020-05-29 06:24  weixiaokun  阅读(179)  评论(0编辑  收藏  举报