zoukankan      html  css  js  c++  java
  • 桥接模式(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

  • 相关阅读:
    中国各城市PM2.5数据间的相关分析
    vue中template的作用及使用
    Vue 点击获得父元素,子元素,兄弟元素(DOM操作)
    解决elementUI中message消息多次重复展现的问题
    Uncaught (in promise) NavigationDuplicated {_name: "NavigationDuplicated"}的解决方法
    v-focus给input设置焦点
    Cannot find name 'template'.Vetur 问题解决
    vue的prototype和拦截器
    Nginx下载启动
    Nginx负载均衡原理
  • 原文地址:https://www.cnblogs.com/youngao/p/11351180.html
Copyright © 2011-2022 走看看