现在我们来学习桥接模式,这个包建在结构这个包下面,bridge,那桥接模式就是把抽象和实现,分离出来,然后中间通过组合,来搭建他们之间的桥梁,那我们现在有一个场景,例如中国有很多银行,有中国农业银行,还有工商银行,那这两个银行也比较好记,一个叫ABC Bank,还有叫ICBC Bank,我们就有自己的账号,那关于我们的储蓄账号呢,分为定期账号,还有活期账号,定义账号可以存三个月,半年一年,银行也有一定的利息,而这种利息是比活期账号利息高很多的,那我们现在抽象的来想一下,那这里面就分两大块,一块是银行,另外一块就是我们的账号,首先我们来创建一个类,这个类是一个接口,为什么要用接口呢,创建完这个接口之后,我们还要具体写他的实现,这个接口就是Account账号

一旦你看到这个图,一定会很清晰的,这些都打开,那我们一起来看一下这个图,我们一起来回顾一下,首先我们创建了Account,这个是什么呢,他是这个桥的实现接口,左侧是实现层,右侧是抽象层,所以桥接模式最重要的是把桥的左侧和桥的右侧,你要桥接的两侧,划分清楚,Account可以理解成,他就是这个桥的实现接口,而下边这两个Account,一个是定期账号,一个是活期账号,他们两个就是具体的实现类,他们来实现Account接口,然后注意,第三步我们创建了Bank,创建了一个抽象类Bank,用的是什么呢,使用了Account这个接口,这个就是桥接模式的核心,注意这个抽象类使用了Account接口,通过什么方式呢,通过组合的方式,所以这条线右侧有一个菱形,一个Bank里面含有一个Account,那下边的ICBCBank,还有ABCBank,他们就是具体继承了Bank,这个抽象类具体的类实现,那我们通过这个桥接模式,把实现部分Account,和抽象部分Bank,进行一个桥接,那当然我们说的实现部分,是指Account的具体的接口实现类,而抽象部分,就是指Bank这个抽象类,而中间的这个横线呢,也就是桥接模式的一个关键,连接两个继承体系的一个桥,当然我们这里面是组合,也有通过聚合方式实现桥接的,如果我们不用这种方式,会怎么样呢,打个比方,我们首先写一个Bank,然后这两个银行爱存不存,还有ABCBank,然后我们在ICBCBank下边,再创建两个账号,一个是SavingAccount,另外一个是DepositAccount,同理呢ABCBank下边,也会有这两个账号,那这导致了一个什么问题,如果我们银行很多,还有账号的类型很多的话,这个子类就要爆炸了,下边会有无数个的类,那前面我们也有说,桥接模式在一定程度上,可以避免子类过多,子类剧增,子类爆炸的情况,那如果我们用刚刚我们说的方式,就是通过最简单的一个继承的方案,所以桥接模式通过组合的方式,通过复合复用原则,来达到抽象层,和实现层,他们两之间进行分离,并且最重要的一点,他们两可以独立的发展,再创建一个银行,在这里面创建银行,继承Bank就可以,在这里面创建一个账号,继承Account就可以,他们两之间就可以无限组合,那这个就桥接模式的精华所在,希望你们能够深入理解一下,在这个模式当中,使用组合优于继承,这个效果是非常非常明显的,那他到底有多方便呢,很简单,我们来写一下Test

注意中间是一个桥梁,最大的特色是连接两个继承体现中间的那座桥,也就是我们看到的一比一的关系,左边是抽象部分,右边是实现部分,抽象部分可以独立的扩展自己,实现部分也可以独立的扩展自己,可以加无数个银行,而账号这边呢,可以加各种理财账号,各种各样的账号,至少不管他们之间如何排列组合,我们都不会发生类爆炸的情况,刚才我们在前面也说了,如果用继承的方式来实现的话,会是什么样子,那希望通过我们的coding实战,对桥接模式有更深刻的理解,还有千万不要忘记委托行为的小坑
package com.learn.design.pattern.structural.bridge;/*** 在这里有两个方法* * * @author Leon.Sun**/
public interface Account {/*** 一个呢是打开我们的账号* 打开账号又分为打开哪个银行的账号呢* 例如leon有工商银行的账号* 还有中国农业银行的账号* 所以这里也是一个抽象* 那既然打开账号呢* 就要返回账号* openAccount这么一个方法* * * @return*/Account openAccount();/*** 还有是查看我们账户的类型* 是活期储蓄* 还是定期储蓄* 还有一个showAccountType* 看一下这个账号的类型* 就现在的场景而言* 我们有中国农业银行* 中国工商银行* 这是两个银行* 还有有活期账号* 还有定期账号* 这个呢是两个不同类型的账号* 他们交叉一下* 就会有四种组合* 那一旦说我们的银行不断的扩展* 账号类型也不断地扩展的话* 那么对于桥接模式* 就再适合不过了* 他们两个都可以随着自己的层级* 进行扩展* 随着我们coding的时候呢* 希望对这一块的理解呢* 会加深* 首先呢我们创建一个定期账号* 来实现这个接口* DepositAccount* * */void showAccountType();}
package com.learn.design.pattern.structural.bridge;/*** 他来实现Account* 实现两个方法* 这个账号是一个定期账号* 我们再创建一个活期账号的类* 新建一个类* SavingAccount* DepositAccount是定期存款* 如果提前取出来的话需要交罚金的* * * * @author Leon.Sun**/
public class DepositAccount implements Account {/*** 写一下这个类的实现* * */@Overridepublic Account openAccount() {/*** 首先输出* "打开定期账号"* * */System.out.println("打开定期账号");/*** 返回值直接new一个* 非常适合回来来看* 写完之后你们先体会* 回头来给大家讲* 因为我几年前在学模式的时候* 当时从上至下的来学习的时候* 理解的并不是很透彻* 但是一旦写完之后* 再回头来看* 一切都非常清晰明了* 我们边写也会边讲* 一起来体会* 我们再回头重点来讲* 那我们继续来coding* 那现在就得写我们的银行类* 创建一个类Bank* * */return new DepositAccount();}@Overridepublic void showAccountType() {/*** 这个是一个定期账号* * 直接到这里* 这是一个定期账号* 那这个时候F8通过* * */System.out.println("这是一个定期账号");}
}
package com.learn.design.pattern.structural.bridge;/*** 他也实现Account接口* 实现这两个方法* SavingAccount是随时可以取钱的那种* * * @author Leon.Sun**/
public class SavingAccount implements Account {/*** 打开这个账号需要返回这个账号* * */@Overridepublic Account openAccount() {/*** 所以我们输出一下打个标记* * */System.out.println("打开活期账号");//.../*** new一个SavingAccount* * */return new SavingAccount();}@Overridepublic void showAccountType() {/*** 直接输出"这是一个活期账号"* * */System.out.println("这是一个活期账号");}
}
package com.learn.design.pattern.structural.bridge;/*** 这个银行类很简单* 他要写成一个抽象类* 为什么呢* 因为现在我们要把Account* 引入到Bank里边* 然后通过这种组合的方式* 交给子类来实现他的行为* 而这个行为就是openAccount* 至少我要确定* 打开的是哪个银行的账号* 那首先呢既然要交给子类* * * @author Leon.Sun**/
public abstract class Bank {/*** protected* 声明一个account* 子类能够拿到Account* 然后我来写一下他的构造器* * */protected Account account;/*** 构造器我可以把account拿过来* 也可以通过set注入的方式* * 然后在父类上也打一个断点* * 所以就把这个account赋值给抽象类Bank* 里面组合的Account* F6单步* 可以看到这个时候已经有值了* * * @param account*/public Bank(Account account){/*** 然后赋值* 把这些断点去掉* 看一下结果* 那在使用桥接模式的时候* 有一个小坑* 这个小坑是什么呢* 例如我们现在打开中国工商银行账号* 然后直接显示了这是一个定期账号* 这个没有什么问题* 但是我们要注意* 我们委托之后* 到底有没有使用他呢* 我们看一下* * */this.account = account;}/*** 然后我们要写一个抽象方法* 那这个方法是什么呢* 正式Account接口的方法* 那一会就知道* 为什么我这个想抽象类里边* 还要写一个抽象方法* 而这个抽象方法* 和接口里面声明的* 抽象方法是一样的* 那这里面我也要强调一下* 声明成一样的方法名* 这个并不是强制的* 那我们声明成一样的方法名呢* 是为了你们更方便的理解* 因为Bank里面的具体的方法* 要委托给Account的openAccount* 这个方法* 所以就把它们声明成一样的方法名* 其实不叫一样的方法名也是OK的* 只不过这种委托关系* 在我们这个case里边* 逻辑比较简单* 并不会增强这个openAccount方法* 所以就直接委托给他* 他们两个的方法名是一样的* 里边的实现所表达的含义也是一样的* 然后这里边再说一下* 看到的Account类* 那在我们现在这个结构中* Account就是具体的实现* 因为我们要通过Account的接口实现* Bank就是抽象* 然后抽象类里面的某个行为* 委托给Account这个接口* 那前面我们也有说* 桥接模式是指抽象和实现分离* 那实现是什么呢* 实现正式Account的两个实现类* 那Account是有名词的含义* 那还有动词* 动词就是报账 查账* 我们可以认为Account是一个行为接口* 里面是两个动作* 一个是open* 一个是show* 打开账号* 还是查看账号类型呢* 这些都是动作* 那这里面还要再强调一次* 抽象和实现分离* 在桥接模式当中* 抽象是指抽象类* 因为还有各种扩展* 而具体的实现呢* 一般也都是行为* 这里也说了* 当然不排除特殊情况* 这里面的account也是动词* 那桥接模式当中的实现* 就是Account的两个接口实现* 而这个方法名字* 并不强制一模一样* 不过我们这里是强制委托* 如果方法要达到的目的是一模一样的* 所以就直接copy这个方法名了* 这里面还是比较灵活的* 并没有强制限制* 那我们现在来创建中国农业银行* ABCBank* * * @return*/abstract Account openAccount();
}
package com.learn.design.pattern.structural.bridge;/*** 他继承Bank* 这个抽象父类* * * @author Leon.Sun**/
public class ABCBank extends Bank {/*** 红线说没有构造器* 我们构造一个* 调用super* 调用父类的构造器* * * @param account*/public ABCBank(Account account) {super(account);}/*** 这里面实现就很简单了* 构造的时候传入的什么Account* 就返回什么Account* 而这个Account正式父类的Account* 所以这里面直接返回Account就可以了* * */@OverrideAccount openAccount() {/*** 直接输出* "打开中国农业银行账号"* 同时我们建立一个爱存不存账号* ICBCBank* * */System.out.println("打开中国农业银行账号");/*** 然后调用了ICBCBank* 很明显这个就是ICBC的银行* 所以他肯定知道这个是中国工商银行* 那具体是什么账号* 他把它再进行一个返回* 那这个返回之后* 就来到了DepositAccount* * 在这里我们有时候写业务逻辑的时候* 经常有忘记委托的这种情况* 隐瞒了一个点* 这个平时在使用桥接模式的时候* 一定不要忘记* 不要把具体的实现自己完成* 而是要委托给Account来实现* 否则创建相同名字的方法* 也就没有意义了* 因为只有通过具体的委托* 以后account里边的openAccount方法* 如果扩展的话* Bank这里边是不需要动的* 不要把这个实现移到openAccount里边* 这里一定要注意* 一定要把你具体的行为委托出去* 委托给谁呢* 正是委托给注入的Account* 那我们再run一下* 来看一下实际的结果* 刚刚那个小坑也是故意埋下的一个伏笔* 希望通过这坑* 一定要印象深刻* 我们再看一下结果* * */account.openAccount();return account;}
}
package com.learn.design.pattern.structural.bridge;/*** 继承Bank这个类* * @author Leon.Sun**/
public class ICBCBank extends Bank {/*** 然后构造器加上* * * @param account*/public ICBCBank(Account account) {/*** 进入这里* * F6* 现在来创建工商银行* 并且把这个账号拿过来了* 他呢又调用父类的构造器* * */super(account);}@OverrideAccount openAccount() {/*** 打开的是工商银行账号* 现在我们来看一下UML图* * 注意这里* 我们打开中国工商银行账号之后* 我们要把具体的行为委托给Account* * */System.out.println("打开中国工商银行账号");/*** 调用它的openAccount* 这样才是真正实现openAccount这个行为* 委托给account* 委托来执行* 所以ABCBank也是一样的* * */account.openAccount();/*** 直接return account* */return account;}
}
package com.learn.design.pattern.structural.bridge;/*** * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 我们创建一个银行* 爱存不存银行* ICBCBank* 这里面放一个DepositAccount* * 首先我们进入他的构造器来看一下* * */Bank icbcBank = new ICBCBank(new DepositAccount());/*** 然后从这里面拿一个账号* icbcBank.openAccount* 打开这个账号* * 这里打开了中国工商银行账号* * 同时打开这个银行之后* 我又打开了定期账号* 这是因为我们把定期账号* 注入到ICBC账号里边* 所以他打开账号的时候* 首先打开中国工商银行账号* 然后打开里面具体的的定期账号* * */Account icbcAccount = icbcBank.openAccount();/*** 然后调用它的showAccountType方法* * 这里是一个定期账号* * 最后show一下AccountType* 也就是这个* 现在这个使用才是非常标准的使用方式* 现在我们再结合前面的原则来说* 如果我们不把具体的实现委托给Account* 这个接口的话* 那我们对ABC Account的实现* 是非常可能不符合迪米特原则的* 那我们回来再看一下* */icbcAccount.showAccountType();/*** 后面直接加一个2* 那现在我们来run一下* 我们来看一下结果* ***/Bank icbcBank2 = new ICBCBank(new SavingAccount());/*** 这里打开一个中国工商银行账号* * */Account icbcAccount2 = icbcBank2.openAccount();/*** 这个是一个活期账号* * */icbcAccount2.showAccountType();/*** 这个时候我再创建一个ABCBank* 这里面就换一下了* SavingAccount* 这个时候即使我需要一个工商银行的SavingAccount* 也是很容易的* 我们直接copy一份出来* * * */Bank abcBank = new ABCBank(new SavingAccount());/*** 打开中国农业银行账号* * */Account abcAccount = abcBank.openAccount();/*** 这是一个活期账号* 那现在debug来跟一个* 非常简单* 我们直接run debug* * */abcAccount.showAccountType();}
}

桥接模式coding相关推荐

  1. Python设计模式-桥接模式

    Python设计模式-桥接模式 基于Python3.5.2,代码如下 #coding:utf-8class Shape():name = ""param = "" ...

  2. python的编程模式-实例解析Python设计模式编程之桥接模式的运用

    这篇文章主要介绍了Python设计模式编程之桥接模式的运用,桥接模式主张把抽象部分与它的实现部分分离,需要的朋友可以参考下 我们先来看一个例子: #encoding=utf-8 # #by panda ...

  3. java设计模式桥接模式最详细讲解,从设计卷到开发看源码

    为什么要使用设计模式? 说到底还是为了程序拓展和移植性,无法就是那几种设计思想 单一职责原则 , 开闭原则  里氏替换原则 ,依赖倒置原则,接口隔离原则,组合复用原则  迪米特法则这些思想和原则就是为 ...

  4. 桥接模式和路由模式区别_【微课堂】路由器设置:桥接模式vs路由模式

    每天接话总有用户要桥接改路由,路由改桥接,改完要提醒重设路由器,否则就要重复呼入,可是怎么设置呢?到底哪个模式更好呢? 小万别着急.今天,我们就来学习一下光猫连接,不同模式下路由器的设置方法. 设置路 ...

  5. 设计模式之桥接模式(Bridge)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式包括:1.FactoryMethod(工厂方法模式):2.Abstract Factory(抽象工厂模式):3.Sin ...

  6. 虚拟机无法使用网卡桥接模式

    重装了好几遍操作系统,换了两个虚拟机,差点怀疑人生-- 最终的原因竟然是win10!!! 1.执行WIN+R 输入services.msc,打开服务管理器(回车). 2.找到Device Instal ...

  7. (转载)深入浅出设计模式——桥接模式(Bridge Pattern)

    模式动机设想如果要绘制矩形.圆形.椭圆.正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色.绿色.蓝色等,此时至少有如下两种设计方案: 第一种设计方案是为每一种形状都提供一套 ...

  8. red hat关于桥接模式连不上外网或者没有IP

    很多人·在启动虚拟机后连接不上外网,即ifconfig没有ip地址,我总结了一下需要注意的地方: 以下全是在桥接模式. 1.在windows中打开任务管理器-->服务中找到一下几个服务,确保它们 ...

  9. 桥接模式(Bridge)

    桥接模式:将抽象部分与它的实现部分分离,使它们能够独立地变化 应用桥接模式解决问题的思路: 假设这样一个应用场景,消息发送模块,消息可以分为普通消息-->加急消息-->特急消息,而发送消息 ...

最新文章

  1. MPB:利用无菌植物和可培养细菌体系研究根系微生物组功能
  2. 斯坦福全球AI报告:人才需求两年暴增35倍,中国机器人部署量涨500%
  3. [转载] 杜拉拉升职记——33 360度评估
  4. 106:HttpResponse对象讲解
  5. PHP实现简单的双色球机选号码
  6. java linux 面试题_java 面试题
  7. 构建 Spring5 源码工程,开启研读Spring源码之路
  8. MySQL(八)MySQL性能优化
  9. 最简单的c语言的编程题目,编程列入考题
  10. 最新 Unity3D鼠标滑轮控制物体放大缩小 [
  11. php知识点汇总与解答_PHP操作员能力倾向问题与解答
  12. 因“5毛钱”惹众怒的丰巢:我错了,下次还敢
  13. Web应用开发平台 OpenJWeb
  14. grub的概念,简单描述一下
  15. Linux课程之linux的发展
  16. 各大洲时区以及Linux环境下修改时区
  17. 和风天气开发平台使用
  18. 【JavaScript】 基础知识
  19. 语音识别(20201030)——麦克风阵列(采集语音信号)
  20. vi php pear,PEAR

热门文章

  1. HDU 4588 Count The Carries 数学
  2. [js开源组件开发]图片放大镜
  3. 【一个iOS官方文档错误】关于keyWindow是否可以接受触摸事件?
  4. IOS 控件 - Swift 集成 IOS 自带 API 扫描二维码
  5. iOS隐藏键盘的几种方式
  6. 让表单文本框只读不可编辑的方法
  7. 使用命令行建立Zend Framework项目
  8. 【新东方老师推荐】老师推荐--听说——这是全球最值得听的、最好听的100首英文歌...
  9. react native 生成APK
  10. 【HRS项目】Axure兴许问题解决---与SVN结合