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