热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入浅出桥梁模式

一、引子桥梁(bright)模式是我介绍的23种模式中的最后一个结构模式。它是一个功能非常强大而且适用于多种情况的模式。二、定义与结构GOF在《设计模式》中给桥梁模式的定义

一、引子

桥梁(bright)模式是我介绍的23种模式中的最后一个结构模式。它是一个功能非常强大而且适用于多种情况的模式。

 

二、定义与结构

GOF在《设计模式》中给桥梁模式的定义为:将抽象部分与它的实现部分分离,使它们都可以独立地变化。这里的抽象部分和实现部分不是我们通常认为的父类与子类、接口与实现类的关系,而是组合关系。也就是说,实现部分是被抽象部分调用,以用来完成(实现)抽象部分的功能。

在《Thinking in Patterns with Java》一书中,作者将抽象部分叫做“front-end”(权且翻译为“前端”),而实现部分叫做“back-end”(后端)。这种叫法要比抽象实现什么的好理解多了。

桥梁模式由如下四种角色组成:

1)        抽象(Abstraction)角色:它定义了抽象类的接口而且维护着一个指向实现(Implementor)角色的引用。

2)        精确抽象(RefinedAbstraction)角色:实现并扩充由抽象角色定义的接口。

3)        实现(Implementor)角色:给出了实现类的接口,这里的接口与抽象角色中的接口可以不一致。

4)        具体实现(ConcreteImplementor)角色:给出了实现角色定义接口的具体实现。

再放上个类图就更清晰了:

       可是这样的结构能够给我们带来什么呢??

       系统设计中,总是充满了各种变数,这是防不慎防的。比如客户代表可能要求修改某个需求,增加某种功能等等。面对这样那样的变动,你只能去不停的修改设计和代码,并且要开始新的一轮测试……。

那采取什么样的方式可以较好的解决变化带给系统的影响?你可以分析变化的种类,将不变的框架使用抽象类定义出来,然后再将变化的内容使用具体的子类来分别实现。这样面向客户的只是一个抽象类,这种方式可以较好的避免为抽象类中现有接口添加新的实现所带来的影响,缩小了变化带来的影响。但是这可能会造成子类数量的爆炸,并且在某些时候不是很灵活。

       但是当你各个子类的行为经常发生变化,或者有一定的重复和组合关系时,我们不妨将这些行为提取出来,也采用接口的方式提供出来,然后以组合的方式将服务提供给原来的子类。这样就达到了前端和被使用的后端独立的变化,而且还达到了后端的重用。

       其实这就是桥梁模式的诞生。

三、实例

我现在唯一知道的使用桥梁模式的应用就是java AWT框架。使用过java AWT的人都知道,在不同系统下开发的软件界面都带有不同系统独有的风格。而在使用AWTAPI的时候根本就没有对不同系统的区分,你也根本就不需要去关心这一点。AWT中正是使用桥梁模式来做到这一点的。

不过我对AWT的代码不熟悉,所以也没有办法在这里讲解一下。下面只能举一个常见的教学代码了:(

以下代码来自《Thinking in Patterns with Java》:

//抽象部分(前端)的抽象角色

class Abstraction {

      //维护着一个指向实现(Implementor)角色的引用     

      private Implementation implementation;

      public Abstraction(Implementation imp) {

             implementation = imp;

      }

      // 下面定义了前端(抽象部分)应该有的接口

      public void service1() {

             //使用了后端(实现部分)已有的接口

             //组合实现功能

             implementation.facility1();

             implementation.facility2();

      }

      public void service2() {

             implementation.facility2();

             implementation.facility3();

      }

      public void service3() {

             implementation.facility1();

             implementation.facility2();

             implementation.facility4();

      }

      // For use by subclasses:

      protected Implementation getImplementation() {

             return implementation;

      }

}

 

//抽象部分(前端)的精确抽象角色

class ClientService1 extends Abstraction {

      public ClientService1(Implementation imp) { super(imp); }

       //使用抽象角色提供的方法组合起来完成某项功能

       //这就是为什么叫精确抽象角色(修正抽象角色)

      public void serviceA() {

             service1();

             service2();

      }

       public void serviceB() {

             service3();

      }

}

 

//另一个精确抽象角色,和上面一样的被我省略了

class ClientService2 extends Abstraction {

 。。。。

       //这里是直接通过实现部分的方法来实现一定的功能

      public void serviceE() {

             getImplementation().facility3();

       }

}

 

//实现部分(后端)的实现角色

interface Implementation {

  //这个接口只是定义了一定的接口

      void facility1();

      void facility2();

      void facility3();

       void facility4();

}

 

//具体实现角色就是要将实现角色提供的接口实现

//并完成一定的功能

//这里省略了

class Implementation1 implements Implementation {

  。。。

 

在上面的程序中还体现出一点特色:就是不仅实现部分和抽象部分所提供的接口可以完全不一样;而且实现部分内部、抽象部分内部的接口也完全可以不一样。但是实现部分要提供类似的功能才行。

 

四、使用环境与优势

由上面我们分析得来的桥梁模式,可以看出来桥梁模式应该适用于以下环境:

1)        当你的系统中有多个地方要使用到类似的行为,或者是多个类似行为的组合时,可以考虑使用桥梁模式来提高重用,并减少因为行为的差异而产生的子类。

2)        系统中某个类的行为可能会有几种不同的变化趋势,为了有效的将变化封装,可以考虑将类的行为抽取出来。

3)        当然上面的情况也可以是这样,行为可能要被不同相似类使用,也可以考虑使用桥梁模式来实现。

       桥梁模式使用了低耦合性的组合代替继承,使得它具备了不少好处:

1)        将可能变化的部分单独封装起来,使得变化产生的影响最小,不用编译不必要的第代码。

2)        抽象部分和实现部分可以单独的变动,并且每一部分的扩充都不会破坏桥梁模式搭起来架子。

3)        对于客户程序来说,你的实现细节是透明的。

Bruce Eckel在《Thinking in patterns with Java》中提到,可以把桥梁模式当作帮助你编码前端和后端独立变化的框架。

 

五、扩展

在《设计模式》一书中提到了使用抽象工厂模式来创建和配置一个桥梁模式。在上面的例子中也使用到了工厂方法模式来得到具体的实现部分。

 

六、总结

以上写出了我对桥梁模式的理解,如有不对之处,还请指正!


推荐阅读
  • 由于工作需要,接手别人用bpel写的工作流程序,一点都不懂就到网上找到一篇入门的文章,觉得这篇不错,就copy下来并添加了读书笔计以红字标记,感激写此文章的人.许多开发人员觉得BPEL很神秘,不知道 ... [详细]
  • 设计模式——模板方法模式的应用和优缺点
    本文介绍了设计模式中的模板方法模式,包括其定义、应用、优点、缺点和使用场景。模板方法模式是一种基于继承的代码复用技术,通过将复杂流程的实现步骤封装在基本方法中,并在抽象父类中定义模板方法的执行次序,子类可以覆盖某些步骤,实现相同的算法框架的不同功能。该模式在软件开发中具有广泛的应用价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了如何清除Eclipse中SVN用户的设置。首先需要查看使用的SVN接口,然后根据接口类型找到相应的目录并删除相关文件。最后使用SVN更新或提交来应用更改。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 微软评估和规划(MAP)的工具包介绍及应用实验手册
    本文介绍了微软评估和规划(MAP)的工具包,该工具包是一个无代理工具,旨在简化和精简通过网络范围内的自动发现和评估IT基础设施在多个方案规划进程。工具包支持库存和使用用于SQL Server和Windows Server迁移评估,以及评估服务器的信息最广泛使用微软的技术。此外,工具包还提供了服务器虚拟化方案,以帮助识别未被充分利用的资源和硬件需要成功巩固服务器使用微软的Hyper - V技术规格。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 下面是自己写的日历控件,在开发中可以当做一个插件来用。该插件共包括:CalendarPop.java日历控件主类ActionButtonListener.java监听动作按钮的监听器DayC ... [详细]
  • 我们使用例如ActionListener的接口时,自己把那些函数定义了就行了。但是我不清楚是谁来调用这个函数呢?例如我自己定义一个接口:publicinterfaceMyInterfa ... [详细]
author-avatar
骑单车追梦的小男孩
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有