【IT168 技术文档】
这几天一直在研究各种各样的设计模式,在学习适配器模式、桥接模式和外观模式模式的时候,发现他们之间存在着一定的关系,实际上模式不适单一存在的,在我们的现实编程生活中往往是几种模式结合使用的。
适配器模式与桥接模式的区别和联系
适配器模式和桥接模式都是间接引用对象,因此可以使系统更灵活,在实现上都涉及从自身以外的一个接口向被引用的对象发出请求。两种模式的区别在于使用场合不同,适配器模式主要解决两个已有接口间的匹配问题,这种情况下被适配的接口的实现往往是一个黑匣子。我们不想,也不能修改这个接口及其实现。同时也不可能控制其演化,只要相关的对象能与系统定义的接口协同工作即可。适配器模式经常用在与第三方产品的功能集成上,采用该模式适应新类型的增加的方式是开发针对这个类型的适配器,如下所示。
桥接模式则不同,参与桥接的接口是稳定的,用户可以扩展和修改桥接中的类,但是不能改变接口。桥接模式通过接口继承或者继承实现功能扩展,如图所示。
按照GOF的说法,桥接模式和适配器模式用于设计的不同阶段,桥接模式用于设计的前期,即在设计类时将类规划为逻辑和实现两个大类,使它们可以分别进行演化;而适配器模式用于设计完成之后,当发现设计完成的类无法协同工作时,可以采用适配器模式。
然而,很多情况下在设计初期就要考虑适配器模式的使用,如涉及大量第三方应用接口的情况。
适配器模式与桥接模式的联合
在实际应用中,桥接模式经常和适配器模式同时出现,如图所示。本文给出一些示例,仅供参考。
这种情况经常出现在需要其他系统提供实现方法时,一个典型的例子是工业控制中的数据采集。不同工控厂家提供的底层数据采集接口通常不同,因此在做上层软件设计时无法预知可能遇到何种接口。为此需要定义一个通用的采集接口,然后针对具体的数据采集系统开发相应的适配器。数据存储需要调用数据采集接口获得数据,而数据可以保存到关系数据库、实时数据库或者文件中。数据存储接口和数据采集结构构成了桥接,如图所示。
同样的结构也经常出现在报表相关的应用中,报表本身结构和报表输出方式完全可以分开,如下图所示。
报表输出可以单独抽象出来与报表的具体形式分开。但报表输出又依赖于具体的输出方式,如果需要输出为PDF格式,则要调用与PDF相关的API,而这是设计所无法控制的,因此这里要使用适配器模式。
适配器模式与外观模式的关系
适配器模式与外观模式有些相似,都是对现相存系统的封装。但这两种模式的意图完全不同,前者使现存系统与正在设计的系统协同工作而后者则为现存系统提供一个更为方便的访问接口。简单地说,适配器模式为事后设计,而外观模式则必须事前设计,因为系统依赖于外观。总之,适配器模式没有引入新的接口,而外观模式则定义了一个全新的接口。
适配器模式用于粒度较小的功能集成,如使用权威单位所规定的无法修改并替换的现有算法模块(油罐的容积算法为国家计量权威单位所规定,需要使用特定的模块),将来也可能升级。这时可以使用适配器模式。
外观模式的使用有时比较难把握,外观接口的定义与设计人员对业务的理解程度有很大关系。如果接口设计过于复杂,则不如直接调用原系统简单;如果接口设计过于简单,有些功能需要调用原有系统才能实现,同样达不到封装目的。在这种情况下,首先要考虑被封装系统的稳定程度。如果系统处于演化阶段,那么接口定义需要复杂一些,以暴露更多的接口。这时,外观模式更像一个大粒度的适配器。被封装系统发生演化时,需要新的外观对象,而这个外观对象起到了适配器的作用。下图所示为这种情况下的结构。
总结
我们讨论了适配器模式、桥接模式和外观模式之间的关系。适配器模式经常用在需要与第三方API协同工作的场合,在功能集成需求越来越多的今天,这种模式的使用频度越来越高,特别是桥接模式与适配器的组合在设计中越来越频繁地出现,几乎已经成为一种新的模式。