(原創) 我的Design Pattern之旅[6] : Adapter Pattern (OO) (Design Pattern) (C/C++) (.NET) (C#) (C++/CLI) (VB)

Abstract
在OO設計裡,我們常會定下interface要求其他class必須實現此interface,以便彼此溝通,若是新開發的專案,問題就不大;若既有的framework/library中,已經有符合需求的class,但唯一可惜的是,『因為interface並不相同』,導致無法和我的class合作,此時可使用Adpater Pattern解決。

Intent
將class的interface轉換成外界所預期的另一種interface,讓原先囿於interface不相容問題而無法協力合作的class能夠兜再一起用[1]。

Introduction
adapter中文為轉換器、轉接器,主要的目的就是將不相容的interface做轉換。現實生活中,處處可以看到adapter,如Notebook內部使用的是DC(直流電),但插頭提供的是AC(交流電),所以必須使用AC to DC adapter將交流電轉換成直流電,Notebook才能使用;又如現在很多Notebook並沒有COM port,取而代之的是USB port,但很多嵌入式系統開發版必須使用COM port才能與PC連接,因此就有USB to COM的adapter,讓Notebook可以和開發版做連接。OO設計也是如此,若interface不相容,則可透過Adapter Pattern解決。

Structure[1]
Class Adapter (使用繼承技術)


Object Adapter (使用組合技術)


Participants[1]
Client
  與符合ITarget interface的object合作。

ITarget
  定義Client所用的與應用領域相關之interface。

Adaptee
  需要被轉換的既有interface。

Adapter
  將Adaptee轉換成ITarget interface。

Collaborations
  Client呼叫Adapter的method,Adapter再去呼叫Adaptee的method完成任務[1]。

Implementation
Class Adapter

ISO C++ (使用多重繼承,對ITarget使用public繼承,對Adaptee使用private繼承,因為Adaptee僅需Adapter內部使用即可。)


C#


C++/CLI


VB


執行結果

Hello Adaptee!! 


Object Adapter

ISO C++


C#


C++/CLI


VB


執行結果

Hello Adaptee!! 


Consequence
Class Adapter和Object Adapter各有優缺點:
Class Adapter
優點:
1.容易override Adaptee原本的行為。
   因為Class Adapter繼承了Adaptee,所以可以輕易的override Adaptee。
2.代碼較精簡。

缺點:
1.只能轉換單一Adaptee。
   因為使用繼承技術,所以Class Adapter的內容會綁死在特定的Adaptee的concreate class或derived class身上,因此Class Adapter無法同時轉換多個Adaptee。(若配合泛型技術,可以解掉此問題,請參閱(原創) 我的Design Pattern之旅[7]:使用泛型改進Adapter Pattern (OO) (Design Pattern) (C/C++) (template) (C++/CLI)

2.無法動態改變欲轉換的Adaptee。
   因為使用繼承技術,在compile-time已經決定了要繼承的Adaptee,所以無法動態改變Adaptee。

Object Adapter
優點:
1.可轉換多個Adaptee。
   因為使用了組合技術,配合polymorphism(多型/多態),所以能轉換class和其derived class。

2.可動態改變欲轉換的Adaptee。
   因為使用了組合技術,可以在run-time的改變欲轉換的Adaptee。

缺點:
1.較難override Adaptee原本的行為。
   若需override Adaptee原本的行為,必須先繼承Adaptee之後,override之,然後Adapter再組合Adaptee的driverd class。

2.代碼較多。

Class Adapter和Object Adapter優缺點剛好互補,可依實際需求決定之,大體上而言,Object Adapter優於Class Adapter,因為彈性較大,且可面對將來未知的class,也應證了那句『多用組合,少用繼承』的Design Pattern三句真言。

Example
(原創) 我的Design Pattern之旅[1]:Strategy Pattern (OO) (Design Pattern) (C?C++) (template) (.NET) (C#)中Grapher使用了Strategy Pattern,為了可動態載入畫Triangle,畫Circle,畫Squre的算法,我們定了IDrawStrategy interface,並且寫了Triangle、Circle、Square三個class實現IDrawStrategy interface,但今天發現在某個framwork/library中(如.NET Framework中的GDI+或DirectX),已經存在畫Triangle、Circle、Square的算法了,所以不需重新自己寫,但因為interface不同,所以Grapher無法使用,且我們又沒有該framework/library的source code,根本無法修改成實現IDrawStrategy interface(如我們根本沒有DirectX或.NET Framework的source code),所以我們只好寫一個DrawAdapter,讓Grapher可以使用之。
Class Adapter



IDrawStrategy interface定的是draw(),但IPaint interface定的是paint(),所以Grapher無法使用,因為無法修改IPaint interface和Triangle class、Circle class、Square class(因為可能在其他Framework內,無source code可修改),所以只好加上TriangleDrawAdapter,CircleDrawAdapter和SquareDrawAdapter做轉換。

ISO C++


C#


C++/CLI


VB


執行結果

Draw Triangle
Draw Circle
Draw Square


Class Adapter的缺點在此範例很明顯,因為使用繼承技術,所以每個Class需要有相對應的Adapter,使用泛型可以稍微解決此問題,不過僅能使用ISO C++和C++/CLI的template來解決,C#、C++/CLI、VB的Generics都無福消受,請參閱 (原創) 我的Design Pattern之旅[7]:使用泛型改進Adapter Pattern (OO) (Design Pattern) (C/C++) (template) (C++/CLI)

Object Adapter

ISO C++


C#


C++/CLI


VB


執行結果

Draw Triangle
Draw Circle
Draw Square


Object Adapter的優點在此範例可以明顯看出,只需一個DrawAdapter就可轉換所有class,未來若有新的class,也不需再修改DrawAdapter,符合OCP原則,且又可動態載入不同的Adaptee。

Conclusion
Design Pattern的修為重在了解class間該如何布局以解決問題,但坊間講Design Pattern的書大都用C++或Java,C#很少,VB更少,本文同時用了ISO C++、C#、C++/CLI、VB來實現Adapter Pattern,各位讀者可依自己的需要,選擇自己喜歡的語言來了解Adapter Pattern。

See Also
(原創) 我的Design Pattern之旅[1]:Strategy Pattern (OO) (Design Pattern) (C?C++) (template) (.NET) (C#)
(原創) 我的Design Pattern之旅[7]:使用泛型改進Adapter Pattern (OO) (Design Pattern) (C/C++) (template) (C++/CLI)

Reference
[1] Gof, Design Patterns,Addison Weseley Longman,1995

posted on 2007-07-16 16:00  真 OO无双  阅读(15865)  评论(6编辑  收藏  举报

导航