文档章节

研磨设计模式之 桥接模式-4

We911
 We911
发布于 2017/02/08 10:14
字数 4277
阅读 4
收藏 0

研磨设计模式之 桥接模式-4

3.4  广义桥接-Java中无处不桥接

        使用Java编写程序,一个很重要的原则就是“面向接口编程”,说得准确点应该是“面向抽象编程”,由于在Java开发中,更多的使用接口而非抽象类,因此通常就说成“面向接口编程”了。
        接口把具体的实现和使用接口的客户程序分离开来,从而使得具体的实现和使用接口的客户程序可以分别扩展,而不会相互影响。使用接口的程序结构如图12所示:


                          图12  使用接口的程序结构示意图


        可能有些朋友会觉得,听起来怎么像是桥接模式的功能呢?没错,如果把桥接模式的抽象部分先稍稍简化一下,暂时不要RefinedAbstraction部分,那么就跟上面的结构图差不多了。去掉RefinedAbstraction后的简化的桥接模式结构示意图如图13所示:


                图13  简化的桥接模式结构示意图


        是不是差不多呢?有朋友可能会觉得还是有很大差异,差异主要在:前面接口的客户程序是直接使用接口对象,不像桥接模式的抽象部分那样,是持有具体实现部分的接口,这就导致画出来的结构图,一个是依赖,一个是聚合关联。
        请思考它们的本质功能,桥接模式中的抽象部分持有具体实现部分的接口,最终目的是什么,还不是需要通过调用具体实现部分的接口中的方法,来完成一定的功能,这跟直接使用接口没有什么不同,只是表现形式有点不一样。再说,前面那个使用接口的客户程序也可以持有相应的接口对象,这样从形式上就一样了。
        也就是说,从某个角度来讲,桥接模式不过就是对“面向抽象编程”这个设计原则的扩展。正是通过具体实现的接口,把抽象部分和具体的实现分离开来,抽象部分相当于是使用实现部分接口的客户程序,这样抽象部分和实现部分就松散耦合了,从而可以实现相互独立的变化。
        这样一来,几乎可以把所有面向抽象编写的程序,都视作是桥接模式的体现,至少算是简化的桥接模式,就算是广义的桥接吧。而Java编程很强调“面向抽象编程”,因此,广义的桥接,在Java中可以说是无处不在。
        再举个大家最熟悉的例子来示例一下。在Java应用开发中,分层实现算是最基本的设计方式了吧,就拿大家最熟的三层架构来说,表现层、逻辑层和数据层,或许有些朋友对它们称呼的名称不同,但都是同一回事情。
三层的基本关系是表现层调用逻辑层,逻辑层调用数据层,通过什么来进行调用呢?当然是接口了,它们的基本结构如图14所示:


           图14  基本的三层架构示意图


        通过接口来进行调用,使得表现层和逻辑层分离开来,也就是说表现层的变化,不会影响到逻辑层,同理逻辑层的变化不会影响到表现层。这也是同一套逻辑层和数据层,就能够同时支持不同的表现层实现的原因,比如支持Swing或Web方式的表现层。
        在逻辑层和数据层之间也是通过接口来调用,同样使得逻辑层和数据层分离开,使得它们可以独立的扩展。尤其是数据层,可能会有很多的实现方式,比如:数据库实现、文件实现等,就算是数据库实现,又有针对不同数据库的实现,如Oracle、DB2等等。
        总之,通过面向抽象编程,三层架构的各层都能够独立的扩展和变化,而不会对其它层次产生影响。这正好是桥接模式的功能,实现抽象和实现的分离,从而使得它们可以独立的变化。当然三层架构不只是在一个地方使用桥接模式,而是至少在两个地方来使用了桥接模式,一个在表现层和逻辑层之间,一个在逻辑层和数据层之间。
        下面先分别看看这两个使用桥接模式的地方的程序结构,然后再综合起来看看整体的程序结构。先看看逻辑层和数据层之间的程序结构,如图15所示:


              图15  逻辑层和数据层的程序结构示意图


 再看看表现层和逻辑层之间的结构示意,如图16所示:


      图16  表现层和逻辑层的结构示意图


 然后再把它们结合起来,看看结合后的程序结构,如图17所示:


                             图17  三层结合的结构示意图


        从广义桥接模式的角度来看,平日熟悉的三层架构其实就是在组合使用桥接模式。从这个图还可以看出,桥接模式是可以连续组合使用的,一个桥接模式的实现部分,可以作为下一个桥接模式的抽象部分。如此类推,可以从三层架构扩展到四层、五层、直到N层架构,都可以使用桥接模式来组合。
        如果从更本质的角度来看,基本上只要是面向抽象编写的Java程序,都可以视为是桥接模式的应用,都是让抽象和实现相分离,从而使它们能独立的变化。不过只要分离的目的达到了,叫不叫桥接模式就无所谓了。


3.5  桥接模式的优缺点

  • 分离抽象和实现部分
        桥接模式分离了抽象和实现部分,从而极大地提高了系统的灵活性。让抽象部分和实现部分独立开来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。
  • 更好的扩展性
        由于桥接模式把抽象和实现部分分离开了,而且分别定义接口,这就使得抽象部分和实现部分可以分别独立的扩展,而不会相互影响,从而大大的提高了系统的可扩展性。
  • 可动态切换实现
        由于桥接模式把抽象和实现部分分离开了,那么在实现桥接的时候,就可以实现动态的选择和使用具体的实现,也就是说一个实现不再是固定的绑定在一个抽象接口上了,可以实现运行期间动态的切换实现。
  • 可减少子类的个数
        根据前面的讲述,对于有两个变化纬度的情况,如果采用继承的实现方式,大约需要两个纬度上的可变化数量的乘积个子类;而采用桥接模式来实现的话,大约需要两个纬度上的可变化数量的和个子类。可以明显地减少子类的个数。


3.6  思考桥接模式

1:桥接模式的本质
        桥接模式的本质:分离抽象和实现
        桥接模式最重要的工作就是分离抽象部分和实现部分,这是解决问题的关键。只有把抽象和实现分离开了,才能够让它们可以独立的变化;只有抽象和实现可以独立的变化,系统才会有更好的可扩展性、可维护性。
        至于其它的好处,比如:可以动态切换实现、可以减少子类个数等。都是把抽象部分和实现部分分离过后,带来的,如果不把抽象部分和实现部分分离开,那就一切免谈了。所以综合来说,桥接模式的本质在于“分离抽象和实现”。


2:对设计原则的体现
(1)桥接模式很好的实现了开闭原则。
        通常应用桥接模式的地方,抽象部分和实现部分都是可变化的,也就是应用会有两个变化纬度,桥接模式就是找到这两个变化,并分别封装起来,从而合理的实现OCP。
        在使用桥接模式的时候,通常情况下,顶层的Abstraction和Implementor是不变的,而具体的Implementor的实现,是可变的,由于Abstraction是通过接口来操作具体的实现,因此具体的Implementor的实现是可以扩展的,根据需要可以有多个具体的实现。
        同样的,RefinedAbstraction也是可变的,它继承并扩展Abstraction,通常在RefinedAbstraction的实现里面,会调用Abstraction中的方法,通过组合使用来完成更多的功能,这些功能常常是与具体业务有关系的功能。
        桥接模式还很好的体现了:多用对象组合,少用对象继承。
        在前面的示例中,如果使用对象继承来扩展功能,不但让对象之间有很强的耦合性,而且会需要很多的子类才能完成相应的功能,前面已经讲述过了,需要两个纬度上的可变化数量的乘积个子类。
        而采用对象的组合,松散了对象之间的耦合性,不但使每个对象变得简单和可维护,还大大减少了子类的个数,根据前面的讲述,大约需要两个纬度上的可变化数量的和这么多个子类。


3:何时选用桥接模式
        建议在如下情况中,选用桥接模式:

  • 如果你不希望在抽象和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象和实现部分分开,然后在程序运行期间来动态的设置抽象部分需要用到的具体的实现,还可以动态切换具体的实现。
  • 如果出现抽象部分和实现部分都应该可以扩展的情况,可以采用桥接模式,让抽象部分和实现部分可以独立的变化,从而可以灵活的进行单独扩展,而不是搅在一起,扩展一边会影响到另一边。
  • 如果希望实现部分的修改,不会对客户产生影响,可以采用桥接模式,客户是面向抽象的接口在运行,实现部分的修改,可以独立于抽象部分,也就不会对客户产生影响了,也可以说对客户是透明的。
  • 如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目。

 

3.7  相关模式

  • 桥接模式和策略模式
        这两个模式有很大的相似之处。
        如果把桥接模式的抽象部分简化来看,如果暂时不去扩展Abstraction,也就是去掉RefinedAbstraction。桥接模式简化过后的结构图参见图13。再看策略模式的结构图参见图17.1。会发现,这个时候它们的结构都类似如图18所示:


                                    图18  桥接模式和策略模式结构示意图
        通过上面的结构图,可以体会到桥接模式和策略模式是如此相似。可以把策略模式的Context视做是使用接口的对象,而Strategy就是某个接口了,具体的策略实现那就相当于接口的具体实现。这样看来的话,某些情况下,可以使用桥接模式来模拟实现策略模式的功能。
        这两个模式虽然相似,也还是有区别的。最主要的是模式的目的不一样,策略模式的目的是封装一系列的算法,使得这些算法可以相互替换;而桥接模式的目的是分离抽象和实现部分,使得它们可以独立的变化。
  • 桥接模式和状态模式
        由于从模式结构上看,状态模式和策略模式是一样的,这两个模式的关系也基本上类似于桥接模式和策略模式的关系。
        只不过状态模式的目的是封装状态对应的行为,并在内部状态改变的时候改变对象的行为。
  • 桥接模式和模板方法模式
        这两个模式有相似之处。
        虽然标准的模板方法模式是采用继承来实现的,但是模板方法也可以通过回调接口的方式来实现,如果把接口的实现独立出去,那就类似于模板方法通过接口去调用具体的实现方法了。这样的结构就和简化的桥接模式类似了。
        可以使用桥接模式来模拟实现模板方法模式的功能。如果在实现Abstraction对象的时候,在里面定义方法,方法里面就是某个固定的算法骨架,也就是说这个方法就相当于模板方法。在模板方法模式里,是把不能确定实现的步骤延迟到子类去实现;现在在桥接模式里面,把不能确定实现的步骤委托给具体实现部分去完成,通过回调实现部分的接口,来完成算法骨架中的某些步骤。这样一来,就可以实现使用桥接模式来模拟实现模板方法模式的功能了。
        使用桥接模式来模拟实现模板方法模式的功能,还有个潜在的好处,就是模板方法也可以很方便的扩展和变化了。在标准的模板方法里面,一个问题就是当模板发生变化的时候,所有的子类都要变化,非常不方便。而使用桥接模式来实现类似的功能,就没有这个问题了。
        另外,这里只是说从实现具体的业务功能上,桥接模式可以模拟实现出模板方法模式能实现的功能,并不是说桥接模式和模板方法模式就变成一样的,或者是桥接模式就可以替换掉模板方法模式了。要注意它们本身的功能、目的、本质思想都是不一样的。
  • 桥接模式和抽象工厂模式
        这两个模式可以组合使用。
        桥接模式中,抽象部分需要获取相应的实现部分的接口对象,那么谁来创建实现部分的具体实现对象呢?这就是抽象工厂模式派上用场的地方。也就是使用抽象工厂模式来创建和配置一个特定的具体实现的对象。
        事实上,抽象工厂主要是用来创建一系列对象的,如果创建的对象很少,或者是很简单,还可以采用简单工厂,可以达到一样的效果,但是会比抽象工厂来得简单。
  • 桥接模式和适配器模式
        这两个模式可以组合使用。
        这两个模式功能是完全不一样的,适配器模式的功能主要是用来帮助无关的类协同工作,重点在解决原本由于接口不兼容而不能一起工作的那些类,使得它们可以一起工作。而桥接模式则重点在分离抽象和实现部分。
        所以在使用上,通常在系统设计完成过后,才会考虑使用适配器模式;而桥接模式,是在系统开始的时候就要考虑使用。
        虽然功能上不一样,这两个模式还是可以组合使用的,比如:已有实现部分的接口,但是有些不太适应现在新的功能对接口的需要,完全抛弃吧,有些功能还用得上,该怎么办呢?那就使用适配器来进行适配,使得旧的接口能够适应新的功能的需要。

 

 

 研磨设计模式结束,谢谢捧场! 

本文转载自:http://blog.csdn.net/liduanw/article/details/8192903

共有 人打赏支持
We911
粉丝 1
博文 63
码字总数 0
作品 0
深圳
程序员
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
0
0
java设计模式-- 单例模式

在很久之前,也就是在大二暑假的时候,那时候看马士兵的视频教程中有提到很多的设计模式。 java的设计模式大致可以分为3大类,23种设计模式。 其中,创建型模式有5种:单例模式、建造者模式、...

爱学习的逃课君
2014/11/27
0
0
(目录)设计模式(可复用面向对象软件的基础)

本系列“设计模式”博客使用Golang语言实现算法。所谓算法是指解决一个问题的步骤,个人觉得不在于语言。小弟只是最近学习Golang,所以顺带熟练一下语法知识,别无它意。 本系列博客主要介绍...

chapin
2015/01/13
0
0
小菜学设计模式——设计模式总结之结构型

1、设计模式总结 设计模式总共23个,但是常用的不到10个,下面就把这23个设计模式进行整理归类,具体如下: 1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型...

learn_more
2015/07/06
0
0
设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信
03/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Centos7安装docker和docker-compose

docker-安装 yum update yum install -y docker-engine docker-compose pip install -U docker-compose...

落叶清风
15分钟前
0
0
7个Python实战项目代码,让你感受下大神是如何起飞的!

关于Python有一句名言:不要重复造轮子。 但是问题有三个: 1、你不知道已经有哪些轮子已经造好了,哪个适合你用。有名有姓的的著名轮子就400多个,更别说没名没姓自己在制造中的轮子。 2、确...

糖宝lsh
16分钟前
0
0
【随记】Maven 与mysql 版本(maven mysql 5.1.38用的最多)

MySQL Connector/J 我的电脑mysql版本为5.7.20-log maven pom.xml 依赖可用5.1.38 pom.xml依赖代码 $加<properties>变量名的实例代码 <properties><!-- data --><mysql-connector-ja......

颖伙虫
18分钟前
0
0
观察者模式

意图: 在对象的内部状态发生变化时,自动通知外部对象进行响应。 构成 被观察者:内部状态有可能被改变,而且又需要通知外部的对象。 观察者:需要对内部状态的改变做出响应的对象。 Java实...

noob_fly
25分钟前
0
0
设计模式之 MVC

MVC 是 模块化思想或者分层思想的实践。 当我们设计一个Web应用的时候,我们的业务流是,读取数据库中的数据,进行逻辑处理,渲染到页面;如果是交互型的页面,那么页面有输入或者事件发生的...

backbye
27分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部