zoukankan      html  css  js  c++  java
  • 桥接模式

    一、桥接模式介绍

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

  • 相关阅读:
    一、flink架构模型
    每日看点
    argparse模块用法实例
    Python 牛刀小试
    spark 编程基础
    我想过的100种暴富机会
    hadoop大数据架构
    centOS7 ip 配置
    classNotFound异常的一个原因
    linux上部署java项目
  • 原文地址:https://www.cnblogs.com/weixk/p/12985262.html
Copyright © 2011-2022 走看看