桥接模式

桥接模式

定义
  1. 将抽象部分与具体部分分离,使他们均可以独立的变化。
  2. 经过组合的方式创建两个雷之间的联系,而不是继承。
类型

结构型java

使用场景
  1. 抽象和具体实现之间的增长更多的灵活性。
  2. 一个类存在两个(或多个)独立变化的维度,且者两个(或多个)维度都须要独立进行扩展。
  3. 不但愿使用多层继承致使系统中类的个数剧增。
优势
  1. 分离抽象部分机器具体实现部分(使抽象和继承再也不在同一个继承层次中,让抽象和实现能够在各自的维度中发展)
  2. 提升了系统的可扩展性
  3. 符合开闭原则
  4. 符合合成复用原则
难点

在使用桥接模式时难点就是须要正确的识别系统中两个独立变化的维度。ide

在写代码以前咱们先假设一个场景,咱们如今要实现一个银行的存款操做,存款的话就包括有活期和按期之分,而后存款也有不一样的银行。咱们就要用代码来模拟这个操做。咱们说桥接模式的难点就在于抽象和实现进行分离。咱们如今先用一个接口当作抽象层。把帐户的相关操做放进这个接口里面。测试

public interface Account {
    Account openAccount();
    void showAccountType();

}

这里定义了两个方法,而后咱们写一下银行的抽象类,一会咱们要委托这个抽象类来执行具体的操做。this

public abstract class Bank {
    protected Account account;
    public Bank(Account account){
        this.account = account;
    }
    abstract Account openAccount();
}

咱们这里定义了一个与接口相同名称的方法,为何要这么作呢?咱们一会再解答。这里有一个帐户的属性,而后将帐户对象注入进来,使用构造器的方式注入。咱们再实现一下具体的银行类。咱们来写一个农业银行ABCBank一个工商银行ICBCBank(爱存不存银行)。这个两个银行继承bank抽象类。实现抽象方法。code

//ABCBank
public class ABCBank extends Bank {
    public ABCBank(Account account) {
        super(account);
    }

    @Override
    Account openAccount() {
        System.out.println("打开中国农业银行帐号");
       account.openAccount();  //这一行很关键,这是委托父类执行操做的代码
        return account;
    }
}
//ICBCBank
public class ICBCBank extends Bank {
    public ICBCBank(Account account) {
        super(account);
    }

    @Override
    Account openAccount() {
        System.out.println("打开中国工商银行帐号");
        account.openAccount();
        return account;
    }
}

这个实现类继承抽象类,在执行openAccount是直接调用父类的方法。这时候咱们说一下为何要让抽象类和接口同样的名称呢,其实这个不同也是能够的,咱们写成同样的只是想让他们表同样的操做,咱们的openAccount方法重点是要调用account的openAccount。对象

// DepositAccount
public class DepositAccount implements Account {
    @Override
    public Account openAccount() {
        System.out.println("打开按期帐号");
        return new DepositAccount();
    }

    @Override
    public void showAccountType() {
        System.out.println("这是一个按期帐号");
    }
}
//SavingAccount
public class SavingAccount implements Account {
    @Override
    public Account openAccount() {
        System.out.println("打开活期帐号");
        //...
        return new SavingAccount();
    }

    @Override
    public void showAccountType() {
        System.out.println("这是一个活期帐号");
    }
}

这两个实现类实现了接口方法。咱们最后看看测试类。继承

public class BridgeTest {
    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();
    }
}

咱们建立一个银行对象将农业银行赋值给他,同时将一个按期帐户传入构造器,注入银行类中,而后银行类在执行openAccount方法调用的是account类的openAccount方法,这样的话咱们就讲account和bank类组合到了一块儿。后面咱们在扩展好比添加bank类时就和account类解耦了,再经过他们的排列组合就能够获得不少结果了。最后咱们看一下运行结果。接口

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