桥接模式(Bridge)---结构型

1 基础知识

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

使用场景:抽象和具体实现之间增加更多的灵活性;一个类存在两个(多个)独立变化的维度,且这两个(多个)维度需要独立扩展即抽象和具体实现独立扩展;不希望使用继承或因多层继承导致类爆炸。

优点:分离抽象部分及具体实现部分;提高了系统的可扩展性;符合开闭原则;符合合成复用原则。缺点:增加了系统的理解与设计难度;需要正确地识别出系统中两个独立变化的维度。

 2 代码示例

使用场景:银行有许多如农业银行、工商银行;银行中的账号类型有定期、活期等。银行和账号之间可以通过组合实现多种场景。

账号接口:

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

账号接口的实现:定期账号  DepositAccount

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

    @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;
    }
    //抽象的方法名字不一定要与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; } }

至此其类关系图可以清楚的体现如何桥接的:

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

 3 相关模式

(1)桥接模式和状态模式

 由于从模式结构上看,状态模式和策略模式是一样的,因此这两个模式的关系也基本上类似于桥接模式和策略模式的关系。只不过状态模式的目的是封装状态对应的行为,并在内部状态改变的时候改变对象的行为。

(2)桥接模式和模板方法模式

 这两个模式有相似之处。虽然标准的模板方法模式是采用继承来实现的,但是模板方法也可以通过回调接口的方式来实现。如果把接口的实现独立出去,那就类似于模板方法通过口去调用具体的实现方法了,这样的结构就和简化的桥接模式类似了。

 可以使用桥接模式来模拟实现模板方法模式的功能。如果在实现 Abstraction对象的时候,在其中定义方法,方法中就是某个固定的算法骨架,也就是说这个方法就相当于模板方法。在模板方法模式中,是把不能确定实现的步骤延迟到子类去实现;现在在桥接模式中,把不能确定实现的步骤委托给具体实现部分去完成,通过回调实现部分的接口,来完成算法骨架中的某些步骤。这样一来,就可以实现使用桥接模式来模拟实现模板方法模式的功能。使用桥接模式来模拟实现模板方法模式的功能,还有一个潜在的好处,就是模板方法也可以很方便地扩展和变化。在标准的模板方法中,一个问题就是当模板发生变化的时候,所有的子类都要变化,非常不方便。而使用桥接模式来实现类似的功能,就没有这个问题。

注:另外,这里只是说从实现具体的业务功能上,桥接模式可以模探实现意模板方法棋式能实现的功能,并不是说桥接模式和模板方法模式就变成一样的,或者是桥接模式就可以替换模板方法模式了。要注意它们本身的功能、目的、本质思想都是不一样的。

(3)桥接模式和抽象工厂模式

 这两个模式可以组合使用。桥接模式中,抽象部分需要获取相应的实现部分的接口对象,那么谁来创建实现部分的具体实现对象呢?这就是抽象工厂模式派上用场的地方。也就是使用抽象工厂模式来创建和配置一个特定的具体的实现对象。事实上,抽象工厂主要是用来创建一系列对象的,如果创建的对象很少,或者是很简单,还可以采用简单工厂,也能达到同样的效果,但是会比抽象工厂来得简单。

(4)桥接模式和适配器模式

  这两个模式可以组合使用。这两个模式功能是完全不一样的,适配器模式的功能主要是用来帮助无关的类协同工作,重点在解决原本由于接口不兼容而不能一起工作的那些类,使得它们可以一起工作。而桥接模式则重点在分离抽象部分和实现部分所以在使用上,通常在系统设计完成以后,才会考虑使用适配器模式;而桥接模式是在系统开始的时候就要考虑使用。虽然功能上不一样,这两个模式还是可以组合使用的,比如,已有实现部分的接口,但是有些不太适应现在新的功能对接口的需要,完全抛弃吧,功能还用得上,该怎么办呢?那就使用适配器来进行适配,使得旧的接口能够适应新的功能的需要。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

posted @ 2019-08-14 12:16  windy杨树  阅读(221)  评论(0编辑  收藏  举报