常见设计模式的解析和实现(C++)---Adapt模式

时间:2022-05-21 05:26:57

刚开始搞C++开发时,项目需求定了之后就开始进入到设计阶段,需要用C++类来抽象很多事物,现在回想起来设计的类相当不成熟,很多地方都可以用经典设计模式来解决,后来经过不断学习和借鉴也能设计出来,只是一直没有关注他们叫什么名称,没有对其进行总结,最近又拿起来看了一下,自己总结了一些门道,供大家讨论和参考,如果有不正确的地方本心虚心请教和聆听.

好了,废话少说接下来主要介绍常用设计模式中Adapt模式的使用和分析.

Adapt模式主要作用:

将一个类的接口转换成客户希望的另外一个接口。Adapt 模式使得原本由于接口不兼容而不能一起工作的那些 类可以一起工作.

 

可能大家听起来很抽象和不容易理解,举个例子就明白了.

例如,有一个绘图编辑器,这个编辑器允许用户绘制和排列基本图元(线、多边型和正文等)生成图片和图表。这个绘图编辑器的关键抽象

是图形对象。图形对象有一个可编辑的形状,并可以绘制自身。图形对象的接口由一个称为S h a p e的抽象类定义。绘图编辑器为每一种图形对象

定义了一个S h a p e的子类: L i n e S h a p e类对应于直线, P o l y g o n S h a p e类对应于多边型,等等。 像L i n e S h a p e和P o l y g o n S h a p e这样的基本几何图形的类比较容易实现,这是由于它们的绘图和编辑功能本来就很有限。但是

对于可以显示和编辑正文的Te x t S h a p e子类来说,实现相当困难,因为即使是基本的正文编辑也要涉及到复杂的屏幕刷新和缓冲区管理。同时,

成品的用户界面工具箱可能已经提供了一个复杂的Te x t Vi e w类用于显示和编辑正文。理想的情况是我们可以复用这个Te x t Vi e w类以实现

Te x t S h a p e类,但是工具箱的设计者当时并没有考虑S h a p e的存在,因此Te x t Vi e w和S h a p e对象不能互换。 一个应用可能会有一些类具有不同的接口并且这些接口互不兼容,在这样的应用中象Te x t Vi e w这样已经存在并且不相关的类如何协同

工作呢?我们可以改变Te x t Vi e w类使它兼容S h a p e类的接口,但前提是必须有这个工具箱的源代码。然而即使我们得到了这些源代码,

修改Te x t Vi e w也是没有什么意义的;因为不应该仅仅为了实现一个应用,工具箱就不得不采用一些与特定领域相关的接口。

我们可以不用上面方法,而定义一个Te x t S h a p e类,由它来适配Te x t Vi e w的接口和S h a p e的接口。我们可以用两种方法做这件事:

1) 继承S h a p e类的接口和Te x t Vi e w的实现,

或2) 将一个Te x t Vi e w实例作为Te x t S h a p e的组成部分,并且使用Te x t Vi e w的接口实现Te x t S h a p e。

这两种方法恰恰对应于A d a p t e r模式的类和对象版本。我们将Te x t S h a p e称之为适配器A d a p t e r。 用类图表示:

常见设计模式的解析和实现(C++)---Adapt模式

 

上面的类图说明了对象适配器实例。它说明了在S h a p e类中声明的B o u n d i n g B o x请求如何被转换成在Te x t Vi e w类中定义

的G e t E x t e n t请求。由于Te x t S h a p e将Te x t Vi e w的接口与S h a p e的接口进行了匹配,因此绘图编辑器就可以复用原先并不兼容

的Te x t Vi e w类。A d a p t e r时常还要负责提供那些被匹配的类所没有提供的功能,上面的类图中说明了适配器如何实现这些职责。

由于绘图编辑器允许用户交互的将每一个S h a p e对象“拖动”到一个新的位置,而Te x t Vi e w设计中没有这种功能。

我们可以实现Te x t S h a p e类的C r e a t e M a n i p u l a t o r操作,从而增加这个缺少的功能,这个操作返回相应的M a n i p u l a t o r

子类的一个实例。M a n i p u l a t o r是一个抽象类,它所描述的对象知道如何驱动S h a p e类响应相应的用户输入,例如将图形拖动到一个新

的位置。对应于不同形状的图形, M a n i p u l a t o r有不同的子类;例如子类Te x t M a n i p u l a t o r对应于Te x t S h a p e。

Te x t S h a p e通过返回一个Te x t M a n i p u l a t o r实例,增加了Te x t Vi e w中缺少而S h a p e需要的功能。

 

以下情况使用A d a p t e r模式 • 你想使用一个已经存在的类,而它的接口不符合你的需求。 • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。 • (仅适用于对象A d a p t e r)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配

它的父类接口。

 

实现: Adapt模式有两种实现办法,一种是采用继承原有接口类的方法,一种是采用组合原有接口类的方法,这里采用的是第二种实现方法.

类适配器使用多重继承对一个接口与另一个接口进行匹配,如下图所示。

 

常见设计模式的解析和实现(C++)---Adapt模式

对象匹配器依赖于对象组合,如下图所示。

 

常见设计模式的解析和实现(C++)---Adapt模式

 

效果

类适配器和对象适配器有不同的权衡。

类适配器

• 用一个具体的A d a p t e r类对A d a p t e e和Ta rg e t进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类A d a p t e r将不能胜任工作。

• 使得A d a p t e r可以重定义A d a p t e e的部分行为,因为A d a p t e r是A d a p t e e的一个子类。

• 仅仅引入了一个对象,并不需要额外的指针以间接得到a d a p t e e。

对象适配器则

• 允许一个A d a p t e r与多个A d a p t e e—即A d a p t e e本身以及它的所有子类(如果有子类的话)—同时工作。A d a p t e r也可以一次给所有的A d a p t e e添加功能。

• 使得重定义A d a p t e e的行为比较困难。这就需要生成A d a p t e e的子类并且使得A d a p t e r引用

这个子类而不是引用A d a p t e e本身。

 

 

这样Adapt设计模式就介绍完了,在实际设计过程中还需考虑很多因素,这里就不一一列举了!