Aha!设计模式(49)-适配器(6)

2019-04-13 13:57发布

实现   尽管Adapter模式的实现方式通常简单直接,但是仍需要注意以下一些问题:
1) 使用C++实现适配器类 在使用C++实现适配器类时,Adapter类应该采用公共方式继承Target类,并且用私有方式继承Adaptee类。因此,Adapter类应该是Target的子类型,但不是Adaptee的子类型。
  这就是适配器模式开头的例子。新系统希望使用既有系统的功能,因此对既有系统进行适配,使之可以在新系统中使用。
2) 可插入的适配器 有许多方法可以实现可插入的适配器。例如,前面描述的TreeDisplay窗口组件可以自动的布置和显示层次式结构,对于它有三种实现方法:   第三种方法是Smalltalk,所以这里是说明前两种方法。
首先(这也是所有这三种实现都要做的)是为Adaptee找到一个“窄”接口,即可用于适配的最小操作集。因为包含较少操作的窄接口相对包含较多操作的宽接口比较容易进行匹配。   这里所说的窄接口指的就是只提供某一方面功能的接口。
对于TreeDisplay而言,被匹配的对象可以是任何一个层次式结构。因此最小接口集合仅包含两个操作:一个操作定义如何在层次结构中表示一个节点,另一个操作返回该节点的子节点。   这是将一个数据结构在TreeView中表达的最低要求,一个用于取得下级节点,一个用于生成当前节点。 对这个窄接口,有以下三个实现途径:
a) 使用抽象操作
在TreeDisplay类中定义窄Adaptee接口相应的抽象操作。这样就由子类来实现这些抽象操作并匹配具体的树结构的对象。例如,DirectoryTreeDisplay子类将通过访问目录结构实现这些操作,如下图所示。   这种情况属于类适配器。   DirectoryTreeDisplay对这个窄接口加以特化,使得它的DirectoryBrowser客户可以用它来显示目录结构。   TreeDisplay提供基本的树结构表示功能,但是不知道从哪里取得下级节点,也不知道如何根据构建当前节点。这两个功能交给了解文件系统功能的DirecotryTreeDisplay来实现。
b) 使用代理对象 在这种方法中,TreeDisplay将访问树结构的请求转发到代理对象。
TreeDisplay的客户进行一些选择,并将这些选择提供给代理对象,这样客户就可以对适配加以控制,如下图所示。
  这种情况属于对象适配器。 例如,有一个DirectoryBrowser,它像前面一样使用TreeDisplay。DirectoryBrowser可能为匹配TreeDisplay和层次目录结构构造出一个较好的代理。
在C++这样的静态类型语言中,需要一个代理的显式接口定义。我们将 TreeDisplay需要的窄接口放入纯虚类TreeAccessorDelegate中,从而指定这样的一个接口。然后我们可以运用继承机制将这个接口融合到我们所选择的代理中— 这里我们选择DirectoryBrowser。如果DirectoryBrowser没有父类我们将采用单继承,否则采用多继承。这种将类融合在一起的方法相对于引入一个新的TreeDisplay子类并单独实现它的操作的方法要容易一些。
  相对于第一种方式,TreeDisplay管理一个适配器对象,这个适配器定义需要实现的窄接口。使用者继承这个适配器类,并且将希望表示的数据结构的接口适配到这个接口上来。   作者观点   虽然1)和2)两种方式看起来非常的不同,但是如果仔细观察,还有存在共通之处的。其共通之处就在于适配对象的选择方法:都是将主要的被调用侧的接口进行适配,以适应调用侧的需求。这个选择和谁先存在无关。   注:   本文中蓝 {MOD}粗体文字都引自《设计模式》一书。   觉得本文有帮助?请分享给更多人。 阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】