(原創) 我的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內部使用即可。)

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ClassAdapter_Classic.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
InBlock.gifDescription : Demo how to implement Class Adapter Classic.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
<iostream>
None.gif
None.gif
using namespace std;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class ITarget dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void request() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adaptee dot.gif{
InBlock.gif
public:
InBlock.gif  
void specificRequest() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adaptee::specificRequest() const dot.gif{
InBlock.gif  cout 
<< "Hello Adaptee!!" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adapter : public ITarget, private Adaptee dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void request() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adapter::request() const dot.gif{
InBlock.gif  specificRequest();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Adapter adapter;
InBlock.gif  adapter.request();
ExpandedBlockEnd.gif}


C#

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ClassAdapter_Classic.cs
InBlock.gifCompiler    : Visual Studio 2005 / C# 2.0
InBlock.gifDescription : Demo how to implement Class Adapter Classic.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif
using System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface ITarget dot.gif{
InBlock.gif  
void request();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adaptee dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void specificRequest() dot.gif{
InBlock.gif    Console.WriteLine(
"Hello Adaptee!!");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adapter : Adaptee, ITarget dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void request() dot.gif{
InBlock.gif    specificRequest();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Client dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
static void Main() dot.gif{
InBlock.gif    ITarget adapter 
= new Adapter();
InBlock.gif    adapter.request();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}


C++/CLI

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ClassAdapter_Classic.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / C++/CLI
InBlock.gifDescription : Demo how to implement Class Adapter Classic.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
"stdafx.h"
None.gif
None.gif
using namespace System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class ITarget dot.gif{
InBlock.gif  
void request();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Adaptee dot.gif{
InBlock.gif
public:
InBlock.gif  
void specificRequest();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adaptee::specificRequest() dot.gif{
InBlock.gif  Console::WriteLine(
"Hello Adaptee!!");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Adapter : public Adaptee, public ITarget dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void request();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adapter::request() dot.gif{
InBlock.gif  specificRequest();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  ITarget
^ adapter = gcnew Adapter();
InBlock.gif  adapter
->request();
ExpandedBlockEnd.gif}


VB

ContractedBlock.gif ExpandedBlockStart.gif
None.gif' 
None.gif'
(C) OOMusou 2007 http://oomusou.cnblogs.com
None.gif

None.gif
'Filename    : DP_AdapterPattern_ClassAdapter_Classic.vb
None.gif'
Compiler    : VB 9
None.gif'
Description : Demo how to implement Class Adapter Classic.
None.gif'
Release     : 07/15/2007 1.0
None.gif'
None.gif
Imports System
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface ITragetInterface ITraget
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub request()Sub request()
ExpandedBlockEnd.gif
End Interface

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class AdapteeClass Adaptee
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub specificRequest()Sub specificRequest()
InBlock.gif    Console.WriteLine(
"Hello Adaptee!!")
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class AdapterClass Adapter
InBlock.gif  
Inherits Adaptee
InBlock.gif  
Implements ITraget
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub request()Sub request() Implements ITraget.request
InBlock.gif    specificRequest()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class ClientClass Client
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Shared Sub Main()Sub Main()
InBlock.gif    
Dim adapter As ITraget = New Adapter()
InBlock.gif    adapter.request()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class


執行結果

None.gif Hello Adaptee!! 


Object Adapter

ISO C++

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ObjectAdapter_Classic.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
InBlock.gifDescription : Demo how to implement Object Adapter Classic.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
<iostream>
None.gif
None.gif
using namespace std;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class ITarget dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void request() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adaptee dot.gif{
InBlock.gif
public:
InBlock.gif  
void specificRequest() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adaptee::specificRequest() const dot.gif{
InBlock.gif  cout 
<< "Hello Adaptee!!" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adapter : public ITarget dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Adapter(Adaptee
* adaptee = 0) : _adaptee(adaptee) dot.gif{}
InBlock.gif  
virtual void request() const;
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  Adaptee
* _adaptee;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adapter::request() const dot.gif{
InBlock.gif  
if (_adaptee)
InBlock.gif    _adaptee
->specificRequest();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Adapter adapter(
&Adaptee());
InBlock.gif  adapter.request();
ExpandedBlockEnd.gif}


C#

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ClassAdapter_Object.cs
InBlock.gifCompiler    : Visual Studio 2005 / C# 2.0
InBlock.gifDescription : Demo how to implement Class Adapter Object.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/
None.gif
using System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface ITarget dot.gif{
InBlock.gif  
void request();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adaptee dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void specificRequest() dot.gif{
InBlock.gif    Console.WriteLine(
"Hello Adaptee!!");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Adapter : ITarget dot.gif{
InBlock.gif  
protected Adaptee _adaptee = null;
InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Adapter() dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Adapter(Adaptee adaptee) dot.gif{
InBlock.gif    _adaptee 
= adaptee;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void request() dot.gif{
InBlock.gif     
if (_adaptee != null)
InBlock.gif      _adaptee.specificRequest();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Client dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
static void Main() dot.gif{
InBlock.gif    Adapter adapter 
= new Adapter(new Adaptee());
InBlock.gif    adapter.request();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}


C++/CLI

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdapterPattern_ObjectAdapter_Classic.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / C++/CLI
InBlock.gifDescription : Demo how to implement Object Adapter Classic.
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/
None.gif#include 
"stdafx.h"
None.gif
None.gif
using namespace System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class ITarget dot.gif{
InBlock.gif  
void request();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Adaptee dot.gif{
InBlock.gif
public:
InBlock.gif  
void specificRequest();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adaptee::specificRequest() dot.gif{
InBlock.gif    Console::WriteLine(
"Hello Adaptee!!");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Adapter : public ITarget dot.gif{
InBlock.gif
protected
InBlock.gif  Adaptee
^ _adaptee;
InBlock.gif
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Adapter() : _adaptee(nullptr) 
dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  Adapter(Adaptee
^ adaptee) : _adaptee(adaptee) dot.gif{}
InBlock.gif  
InBlock.gif
public:
InBlock.gif  
virtual void request();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Adapter::request() dot.gif{
InBlock.gif  
if (_adaptee != nullptr)
InBlock.gif    _adaptee
->specificRequest();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Adapter
^ adapter = gcnew Adapter(gcnew Adaptee);
InBlock.gif  adapter
->request();
ExpandedBlockEnd.gif}


VB

ContractedBlock.gif ExpandedBlockStart.gif
None.gif' 
None.gif'
(C) OOMusou 2007 http://oomusou.cnblogs.com
None.gif

None.gif
'Filename    : DP_AdapterPattern_ObjectAdapter_Classic.vb
None.gif'
Compiler    : VB 9
None.gif'
Description : Demo how to implement Object Adapter Classic.
None.gif'
Release     : 07/15/2007 1.0
None.gif'
None.gif
Imports System
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface ITargetInterface ITarget
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub request()Sub request()
ExpandedBlockEnd.gif
End Interface

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class AdapteeClass Adaptee
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub specificRequest()Sub specificRequest()
InBlock.gif    Console.WriteLine(
"Hello Adaptee!!")
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class AdapterClass Adapter
InBlock.gif  
Implements ITarget
InBlock.gif
InBlock.gif  
Protected _adaptee As Adaptee
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub New()Sub New(Optional ByRef adaptee As Adaptee = Nothing)
InBlock.gif    _adaptee 
= adaptee
ExpandedSubBlockEnd.gif  
End Sub

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub request()Sub request() Implements ITarget.request
InBlock.gif    
If _adaptee IsNot Nothing Then
InBlock.gif      _adaptee.specificRequest()
InBlock.gif    
End If
InBlock.gif
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class ClientClass Client
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Shared Sub Main()Sub Main()
InBlock.gif    
Dim adapter As ITarget = New Adapter(New Adaptee())
InBlock.gif    adapter.request()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class


執行結果

None.gif 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++

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Class.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
InBlock.gifDescription : Demo how to use Strategy Pattern with Adapter Pattern (Class).
InBlock.gifRelease     : 07/15/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
<iostream>
None.gif
using namespace std;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class IDrawStrategy dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Grapher dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher(IDrawStrategy
* drawStrategy = 0) : _drawStrategy(drawStrategy) dot.gif{}
InBlock.gif  
InBlock.gif
public:
InBlock.gif  
void drawShape() const;
InBlock.gif  
void setShape(IDrawStrategy* drawStrategy);
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IDrawStrategy
* _drawStrategy;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::drawShape() const dot.gif{
InBlock.gif  
if (_drawStrategy)
InBlock.gif      _drawStrategy
->draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::setShape(IDrawStrategy* drawStrategy) dot.gif{
InBlock.gif  _drawStrategy 
= drawStrategy;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Triangle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Triangle::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Triangle" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Circle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Circle::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Circle" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Square : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Square::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Square" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class TriangleDrawAdapter : public IDrawStrategy, private Triangle dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void TriangleDrawAdapter::draw() const dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class CircleDrawAdapter : public IDrawStrategy, private Circle dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void CircleDrawAdapter::draw() const dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class SquareDrawAdapter : public IDrawStrategy, private Square dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void SquareDrawAdapter::draw() const dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Grapher grapher(
&TriangleDrawAdapter());
InBlock.gif  grapher.drawShape();
InBlock.gif  
InBlock.gif  grapher.setShape(
&CircleDrawAdapter());
InBlock.gif  grapher.drawShape();
InBlock.gif  
InBlock.gif  grapher.setShape(
&SquareDrawAdapter());
InBlock.gif  grapher.drawShape();
ExpandedBlockEnd.gif}


C#

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Class.cs
InBlock.gifCompiler    : Visual Studio 2005 / C# 2.0
InBlock.gifDescription : Demo how to use Strategy Pattern with Adapter Pattern (Class)
InBlock.gifRelease     : 07/11/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif
using System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface IDrawStrategy dot.gif{
InBlock.gif  
void draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Grapher dot.gif{
InBlock.gif  
protected IDrawStrategy _drawStrategy = null;
InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Grapher() dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Grapher(IDrawStrategy drawStrategy) dot.gif{
InBlock.gif    _drawStrategy 
= drawStrategy;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void drawShape() dot.gif{
InBlock.gif    
if (_drawStrategy != null)
InBlock.gif      _drawStrategy.draw();
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void setShape(IDrawStrategy drawStrategy) dot.gif{
InBlock.gif    _drawStrategy 
= drawStrategy;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface IPaint dot.gif{
InBlock.gif  
void paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Triangle : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Triangle");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Circle : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Circle");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Square : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Square");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class TriangleDrawAdapter : Triangle, IDrawStrategy dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void draw() dot.gif{
InBlock.gif    paint();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class CircleDrawAdapter : Circle, IDrawStrategy dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void draw() dot.gif{
InBlock.gif    paint();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class SquareDrawAdapter : Square, IDrawStrategy dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void draw() dot.gif{
InBlock.gif    paint();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Client dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
static void Main() dot.gif{
InBlock.gif    Grapher grapher 
= new Grapher(new TriangleDrawAdapter());
InBlock.gif    grapher.drawShape();
InBlock.gif  
InBlock.gif    grapher.setShape(
new CircleDrawAdapter());
InBlock.gif    grapher.drawShape();
InBlock.gif  
InBlock.gif    grapher.setShape(
new SquareDrawAdapter());
InBlock.gif    grapher.drawShape();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}


C++/CLI

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Class.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / C++/CLI
InBlock.gifDescription : Demo how to use Strategy Pattern with Adapter Pattern (Class)
InBlock.gifRelease     : 07/12/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
"stdafx.h"
None.gif
using namespace System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class IDrawStrategy dot.gif{
InBlock.gif  
void draw();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Grapher dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher() : _drawStrategy(nullptr) 
dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher(IDrawStrategy
^ drawStrategy) : _drawStrategy(drawStrategy) dot.gif{}
InBlock.gif  
InBlock.gif
public:
InBlock.gif  
void drawShape();
InBlock.gif  
void setShape(IDrawStrategy^ drawStrategy);
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IDrawStrategy
^ _drawStrategy;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::drawShape() dot.gif{
InBlock.gif  
if (_drawStrategy != nullptr)
InBlock.gif      _drawStrategy
->draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::setShape(IDrawStrategy^ drawStrategy) dot.gif{
InBlock.gif  _drawStrategy 
= drawStrategy;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class IPaint dot.gif{
InBlock.gif  
void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Triangle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Triangle::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Triangle");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Circle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Circle::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Circle");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Square : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Square::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Square");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class TriangleDrawAdapter : public IDrawStrategy, public Triangle dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void TriangleDrawAdapter::draw() dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class CircleDrawAdapter : public IDrawStrategy, public Circle dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void CircleDrawAdapter::draw() dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class SquareDrawAdapter : public IDrawStrategy, public Square dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void SquareDrawAdapter::draw() dot.gif{
InBlock.gif  paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Grapher
^ grapher = gcnew Grapher(gcnew TriangleDrawAdapter);
InBlock.gif  grapher
->drawShape();
InBlock.gif  
InBlock.gif  grapher
->setShape(gcnew CircleDrawAdapter);
InBlock.gif  grapher
->drawShape();
InBlock.gif  
InBlock.gif  grapher
->setShape(gcnew SquareDrawAdapter);
InBlock.gif  grapher
->drawShape();
ExpandedBlockEnd.gif}


VB

ContractedBlock.gif ExpandedBlockStart.gif
None.gif' 
None.gif'
(C) OOMusou 2007 http://oomusou.cnblogs.com
None.gif

None.gif
'Filename    : DP_AdpaterPattern_Strategy_Class.vb
None.gif'
Compiler    : VB 9
None.gif'
Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
None.gif'
Release     : 07/12/2007 1.0
None.gif'
None.gif
Imports System
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface IDrawStrategyInterface IDrawStrategy
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub draw()Sub draw()
ExpandedBlockEnd.gif
End Interface

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class GrapherClass Grapher
InBlock.gif  
Protected _drawStrategy As IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub New()Sub New(Optional ByRef drawStrategy As IDrawStrategy = Nothing)
InBlock.gif    _drawStrategy 
= drawStrategy
ExpandedSubBlockEnd.gif  
End Sub

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub drawShape()Sub drawShape()
InBlock.gif    
If _drawStrategy IsNot Nothing Then
InBlock.gif      _drawStrategy.draw()
InBlock.gif    
End If
ExpandedSubBlockEnd.gif  
End Sub

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub setShape()Sub setShape(ByRef drawStrategy As IDrawStrategy)
InBlock.gif    _drawStrategy 
= drawStrategy
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface IPaintInterface IPaint
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub paint()Sub paint()
ExpandedBlockEnd.gif
End Interface

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class TriangleClass Triangle
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Triangle")
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class CircleClass Circle
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Circle")
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class SquareClass Square
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Square")
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class TriangleDrawAdapterClass TriangleDrawAdapter
InBlock.gif  
Inherits Triangle
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class CircleDrawAdapterClass CircleDrawAdapter
InBlock.gif  
Inherits Circle
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class SquareDrawAdapterClass SquareDrawAdapter
InBlock.gif  
Inherits Square
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class

None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class ClientClass Client
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Shared Sub Main()Sub Main()
InBlock.gif    
Dim grapher As Grapher = New Grapher(New TriangleDrawAdapter())
InBlock.gif    grapher.drawShape()
InBlock.gif
InBlock.gif    grapher.setShape(
New CircleDrawAdapter())
InBlock.gif    grapher.drawShape()
InBlock.gif
InBlock.gif    grapher.setShape(
New SquareDrawAdapter())
InBlock.gif    grapher.drawShape()
ExpandedSubBlockEnd.gif  
End Sub

ExpandedBlockEnd.gif
End Class


執行結果

None.gif Draw Triangle
None.gifDraw Circle
None.gifDraw 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++

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Object.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
InBlock.gifDescription : Demo how to use Strategy Pattern with Adapter Pattern (Object)
InBlock.gifRelease     : 07/11/2007 1.0
ExpandedBlockEnd.gif
*/

None.gif#include 
<iostream>
None.gif
using namespace std;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class IDrawStrategy dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void draw() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Grapher dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher(IDrawStrategy
* drawStrategy = 0) : _drawStrategy(drawStrategy) dot.gif{}
InBlock.gif  
InBlock.gif
public:
InBlock.gif  
void drawShape() const;
InBlock.gif  
void setShape(IDrawStrategy* drawStrategy);
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IDrawStrategy
* _drawStrategy;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::drawShape() const dot.gif{
InBlock.gif  
if (_drawStrategy)
InBlock.gif      _drawStrategy
->draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::setShape(IDrawStrategy* drawStrategy) dot.gif{
InBlock.gif  _drawStrategy 
= drawStrategy;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint() const = 0;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Triangle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Triangle::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Triangle" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Circle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Circle::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Circle" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Square : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
void paint() const;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Square::paint() const dot.gif{
InBlock.gif  cout 
<< "Draw Square" << endl;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class DrawAdapter : public IDrawStrategy dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  DrawAdapter(IPaint
* adaptee = 0) : _adaptee(adaptee) dot.gif{}
InBlock.gif  
virtual void draw() const;
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IPaint
* _adaptee;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void DrawAdapter::draw() const dot.gif{
InBlock.gif  _adaptee
->paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Grapher grapher(
&DrawAdapter(&Triangle()));
InBlock.gif  grapher.drawShape();
InBlock.gif  
InBlock.gif  grapher.setShape(
&DrawAdapter(&Circle()));
InBlock.gif  grapher.drawShape();
InBlock.gif  
InBlock.gif  grapher.setShape(
&DrawAdapter(&Square()));
InBlock.gif  grapher.drawShape();
ExpandedBlockEnd.gif}


C#

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Object.cs
InBlock.gifCompiler    : Visual Studio 2005 / Visual C# 2.0
InBlock.gifDescription : Demo how to use Strategy Pattern with Adapter Pattern (Object)
InBlock.gifRelease     : 07/11/2007 1.0
ExpandedBlockEnd.gif
*/
None.gif
using System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface IDrawStrategy dot.gif{
InBlock.gif  
void draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Grapher dot.gif{
InBlock.gif  
protected IDrawStrategy _drawStrategy = null;
InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Grapher() dot.gif{}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Grapher(IDrawStrategy drawStrategy) dot.gif{
InBlock.gif     _drawStrategy 
= drawStrategy;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void drawShape() dot.gif{
InBlock.gif    
if (_drawStrategy != null)
InBlock.gif      _drawStrategy.draw();
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void setShape(IDrawStrategy drawStrategy) dot.gif{
InBlock.gif    _drawStrategy 
= drawStrategy;
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface IPaint dot.gif{
InBlock.gif  
void paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Triangle : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Triangle");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Circle : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Circle");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Square : IPaint dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void paint() dot.gif{
InBlock.gif    Console.WriteLine(
"Draw Square");
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class DrawAdapter : IDrawStrategy dot.gif{
InBlock.gif  
protected IPaint _adaptee = null;
InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DrawAdapter() dot.gif{}
InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public DrawAdapter(IPaint adaptee) dot.gif{
InBlock.gif    _adaptee 
= adaptee;
ExpandedSubBlockEnd.gif  }

InBlock.gif  
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void draw() dot.gif{
InBlock.gif    _adaptee.paint();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class Client dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif  
static void Main() dot.gif{
InBlock.gif    Grapher grapher 
= new Grapher(new DrawAdapter(new Triangle()));
InBlock.gif    grapher.drawShape();
InBlock.gif  
InBlock.gif    grapher.setShape(
new DrawAdapter(new Circle()));
InBlock.gif    grapher.drawShape();
InBlock.gif  
InBlock.gif    grapher.setShape(
new DrawAdapter(new Square()));
InBlock.gif    grapher.drawShape();
ExpandedSubBlockEnd.gif  }

ExpandedBlockEnd.gif}


C++/CLI

ContractedBlock.gif ExpandedBlockStart.gif
ExpandedBlockStart.gifContractedBlock.gif/**//* 
InBlock.gif(C) OOMusou 2007 
http://oomusou.cnblogs.com
InBlock.gif
InBlock.gifFilename    : DP_AdpaterPattern_Strategy_Object.cpp
InBlock.gifCompiler    : Visual C++ 8.0 / C++/CLI
InBlock.gifDescription : Demo how to use Strategy Pattern with Adpater Pattern (Object)
InBlock.gifRelease     : 07/12/2007 1.0
ExpandedBlockEnd.gif
*/
None.gif#include 
"stdafx.h"
None.gif
using namespace System;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class IDrawStrategy dot.gif{
InBlock.gif  
void draw();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Grapher dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher() : _drawStrategy(nullptr) 
dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  Grapher(IDrawStrategy
^ drawStrategy) : _drawStrategy(drawStrategy) dot.gif{}
InBlock.gif  
InBlock.gif
public:
InBlock.gif  
void drawShape();
InBlock.gif  
void setShape(IDrawStrategy^ drawStrategy);
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IDrawStrategy
^ _drawStrategy;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::drawShape() dot.gif{
InBlock.gif  
if (_drawStrategy != nullptr)
InBlock.gif      _drawStrategy
->draw();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Grapher::setShape(IDrawStrategy^ drawStrategy) dot.gif{
InBlock.gif  _drawStrategy 
= drawStrategy;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface class IPaint dot.gif{
InBlock.gif  
void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Triangle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Triangle::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Triangle");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Circle : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Circle::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Circle");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class Square : public IPaint dot.gif{
InBlock.gif
public:
InBlock.gif  
virtual void paint();
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void Square::paint() dot.gif{
InBlock.gif  Console::WriteLine(
"Draw Square");
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
ref class DrawAdapter : public IDrawStrategy dot.gif{
InBlock.gif
public:
ExpandedSubBlockStart.gifContractedSubBlock.gif  DrawAdapter() : _adaptee(nullptr) 
dot.gif{}
ExpandedSubBlockStart.gifContractedSubBlock.gif  DrawAdapter(IPaint
^ adaptee) : _adaptee(adaptee) dot.gif{}
InBlock.gif  
virtual void draw();
InBlock.gif  
InBlock.gif
protected:
InBlock.gif  IPaint
^ _adaptee;
ExpandedBlockEnd.gif}
;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
void DrawAdapter::draw() dot.gif{
InBlock.gif  _adaptee
->paint();
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
int main() dot.gif{
InBlock.gif  Grapher
^ grapher = gcnew Grapher(gcnew DrawAdapter(gcnew Triangle));
InBlock.gif  grapher
->drawShape();
InBlock.gif  
InBlock.gif  grapher
->setShape(gcnew DrawAdapter(gcnew Circle));
InBlock.gif  grapher
->drawShape();
InBlock.gif  
InBlock.gif  grapher
->setShape(gcnew DrawAdapter(gcnew Square));
InBlock.gif  grapher
->drawShape();
ExpandedBlockEnd.gif}


VB

ContractedBlock.gif ExpandedBlockStart.gif
None.gif' 
None.gif'
(C) OOMusou 2007 http://oomusou.cnblogs.com
None.gif

None.gif
'Filename    : DP_AdpaterPattern_Strategy_Class.vb
None.gif'
Compiler    : VB 9
None.gif'
Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
None.gif'
Release     : 07/12/2007 1.0
None.gif'
None.gif
Imports System
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface IDrawStrategyInterface IDrawStrategy
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub draw()Sub draw()
ExpandedBlockEnd.gif
End Interface
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class GrapherClass Grapher
InBlock.gif  
Protected _drawStrategy As IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub New()Sub New(Optional ByRef drawStrategy As IDrawStrategy = Nothing)
InBlock.gif    _drawStrategy 
= drawStrategy
ExpandedSubBlockEnd.gif  
End Sub
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub drawShape()Sub drawShape()
InBlock.gif    
If _drawStrategy IsNot Nothing Then
InBlock.gif      _drawStrategy.draw()
InBlock.gif    
End If
ExpandedSubBlockEnd.gif  
End Sub
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub setShape()Sub setShape(ByRef drawStrategy As IDrawStrategy)
InBlock.gif    _drawStrategy 
= drawStrategy
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Interface IPaintInterface IPaint
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Sub paint()Sub paint()
ExpandedBlockEnd.gif
End Interface
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class TriangleClass Triangle
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Triangle")
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class CircleClass Circle
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Circle")
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class SquareClass Square
InBlock.gif  
Implements IPaint
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub paint()Sub paint() Implements IPaint.paint
InBlock.gif    Console.WriteLine(
"Draw Square")
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class TriangleDrawAdapterClass TriangleDrawAdapter
InBlock.gif  
Inherits Triangle
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class CircleDrawAdapterClass CircleDrawAdapter
InBlock.gif  
Inherits Circle
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class SquareDrawAdapterClass SquareDrawAdapter
InBlock.gif  
Inherits Square
InBlock.gif  
Implements IDrawStrategy
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
InBlock.gif    
Me.paint()
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Class ClientClass Client
ExpandedSubBlockStart.gifContractedSubBlock.gif  
Shared Sub Main()Sub Main()
InBlock.gif    
Dim grapher As Grapher = New Grapher(New TriangleDrawAdapter())
InBlock.gif    grapher.drawShape()
InBlock.gif
InBlock.gif    grapher.setShape(
New CircleDrawAdapter())
InBlock.gif    grapher.drawShape()
InBlock.gif
InBlock.gif    grapher.setShape(
New SquareDrawAdapter())
InBlock.gif    grapher.drawShape()
ExpandedSubBlockEnd.gif  
End Sub
ExpandedBlockEnd.gif
End Class


執行結果

None.gif Draw Triangle
None.gifDraw Circle
None.gifDraw 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值