在OO設計裡,我們常會定下interface要求其他class必須實現此interface,以便彼此溝通,若是新開發的專案,問題就不大;若既有的framework/library中,已經有符合需求的class,但唯一可惜的是,『可能interface並不相同』,導致無法和我的class合作,此時可使用Adpater Pattern解決。
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 (使用繼承技術)
![](/images/cnblogs_com/oomusou/ClassAdapterClassic2.jpg)
Object Adapter (使用組合技術)
![](/images/cnblogs_com/oomusou/ObjectAdapterClassic1.jpg)
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內部使用即可。)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ClassAdapter_Classic.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to implement Class Adapter Classic.
Release : 07/15/2007 1.0
*/
#include <iostream>
![](/Images/OutliningIndicators/None.gif)
using namespace std;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class ITarget
{
public:
virtual void request() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adaptee
{
public:
void specificRequest() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adaptee::specificRequest() const
{
cout << "Hello Adaptee!!" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adapter : public ITarget, private Adaptee
{
public:
virtual void request() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adapter::request() const
{
specificRequest();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Adapter adapter;
adapter.request();
}
C#
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ClassAdapter_Classic.cs
Compiler : Visual Studio 2005 / C# 2.0
Description : Demo how to implement Class Adapter Classic.
Release : 07/15/2007 1.0
*/
using System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface ITarget
{
void request();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adaptee
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void specificRequest()
{
Console.WriteLine("Hello Adaptee!!");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adapter : Adaptee, ITarget
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void request()
{
specificRequest();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Client
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
static void Main()
{
ITarget adapter = new Adapter();
adapter.request();
}
}
C++/CLI
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ClassAdapter_Classic.cpp
Compiler : Visual C++ 8.0 / C++/CLI
Description : Demo how to implement Class Adapter Classic.
Release : 07/15/2007 1.0
*/
#include "stdafx.h"
![](/Images/OutliningIndicators/None.gif)
using namespace System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class ITarget
{
void request();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Adaptee
{
public:
void specificRequest();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adaptee::specificRequest()
{
Console::WriteLine("Hello Adaptee!!");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Adapter : public Adaptee, public ITarget
{
public:
virtual void request();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adapter::request()
{
specificRequest();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
ITarget^ adapter = gcnew Adapter();
adapter->request();
}
VB
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
'
'(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/None.gif)
'Filename : DP_AdapterPattern_ClassAdapter_Classic.vb
'Compiler : VB 9
'Description : Demo how to implement Class Adapter Classic.
'Release : 07/15/2007 1.0
'
Imports System
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface ITragetInterface ITraget
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub request()Sub request()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class AdapteeClass Adaptee
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub specificRequest()Sub specificRequest()
Console.WriteLine("Hello Adaptee!!")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class AdapterClass Adapter
Inherits Adaptee
Implements ITraget
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub request()Sub request() Implements ITraget.request
specificRequest()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class ClientClass Client
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Shared Sub Main()Sub Main()
Dim adapter As ITraget = New Adapter()
adapter.request()
End Sub
End Class
執行結果
Hello Adaptee!!
Object Adapter
ISO C++
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ObjectAdapter_Classic.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to implement Object Adapter Classic.
Release : 07/15/2007 1.0
*/
#include <iostream>
![](/Images/OutliningIndicators/None.gif)
using namespace std;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class ITarget
{
public:
virtual void request() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adaptee
{
public:
void specificRequest() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adaptee::specificRequest() const
{
cout << "Hello Adaptee!!" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adapter : public ITarget
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Adapter(Adaptee* adaptee = 0) : _adaptee(adaptee)
{}
virtual void request() const;
protected:
Adaptee* _adaptee;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adapter::request() const
{
if (_adaptee)
_adaptee->specificRequest();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Adapter adapter(&Adaptee());
adapter.request();
}
C#
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ClassAdapter_Object.cs
Compiler : Visual Studio 2005 / C# 2.0
Description : Demo how to implement Class Adapter Object.
Release : 07/15/2007 1.0
*/
using System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface ITarget
{
void request();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adaptee
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void specificRequest()
{
Console.WriteLine("Hello Adaptee!!");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Adapter : ITarget
{
protected Adaptee _adaptee = null;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Adapter()
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void request()
{
if (_adaptee != null)
_adaptee.specificRequest();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Client
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
static void Main()
{
Adapter adapter = new Adapter(new Adaptee());
adapter.request();
}
}
C++/CLI
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdapterPattern_ObjectAdapter_Classic.cpp
Compiler : Visual C++ 8.0 / C++/CLI
Description : Demo how to implement Object Adapter Classic.
Release : 07/15/2007 1.0
*/
#include "stdafx.h"
![](/Images/OutliningIndicators/None.gif)
using namespace System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class ITarget
{
void request();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Adaptee
{
public:
void specificRequest();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adaptee::specificRequest()
{
Console::WriteLine("Hello Adaptee!!");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Adapter : public ITarget
{
protected:
Adaptee^ _adaptee;
![](/Images/OutliningIndicators/InBlock.gif)
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Adapter() : _adaptee(nullptr)
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Adapter(Adaptee^ adaptee) : _adaptee(adaptee)
{}
public:
virtual void request();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Adapter::request()
{
if (_adaptee != nullptr)
_adaptee->specificRequest();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Adapter^ adapter = gcnew Adapter(gcnew Adaptee);
adapter->request();
}
VB
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
'
'(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/None.gif)
'Filename : DP_AdapterPattern_ObjectAdapter_Classic.vb
'Compiler : VB 9
'Description : Demo how to implement Object Adapter Classic.
'Release : 07/15/2007 1.0
'
Imports System
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface ITargetInterface ITarget
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub request()Sub request()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class AdapteeClass Adaptee
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub specificRequest()Sub specificRequest()
Console.WriteLine("Hello Adaptee!!")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class AdapterClass Adapter
Implements ITarget
![](/Images/OutliningIndicators/InBlock.gif)
Protected _adaptee As Adaptee
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub New()Sub New(Optional ByRef adaptee As Adaptee = Nothing)
_adaptee = adaptee
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub request()Sub request() Implements ITarget.request
If _adaptee IsNot Nothing Then
_adaptee.specificRequest()
End If
![](/Images/OutliningIndicators/InBlock.gif)
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class ClientClass Client
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Shared Sub Main()Sub Main()
Dim adapter As ITarget = New Adapter(New Adaptee())
adapter.request()
End Sub
End Class
執行結果
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
![](/images/cnblogs_com/oomusou/dp_strategy_class_adapter1.jpg)
IDrawStrategy interface定的是draw(),但IPaint interface定的是paint(),所以Grapher無法使用,因為無法修改IPaint interface和Triangle class、Circle class、Square class(因為可能在其他Framework內,無source code可修改),所以只好加上TriangleDrawAdapter,CircleDrawAdapter和SquareDrawAdapter做轉換。
ISO C++
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Class.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to use Strategy Pattern with Adapter Pattern (Class).
Release : 07/15/2007 1.0
*/
#include <iostream>
using namespace std;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class IDrawStrategy
{
public:
virtual void draw() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Grapher
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher(IDrawStrategy* drawStrategy = 0) : _drawStrategy(drawStrategy)
{}
public:
void drawShape() const;
void setShape(IDrawStrategy* drawStrategy);
protected:
IDrawStrategy* _drawStrategy;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::drawShape() const
{
if (_drawStrategy)
_drawStrategy->draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::setShape(IDrawStrategy* drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class IPaint
{
public:
virtual void paint() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Triangle : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Triangle::paint() const
{
cout << "Draw Triangle" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Circle : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Circle::paint() const
{
cout << "Draw Circle" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Square : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Square::paint() const
{
cout << "Draw Square" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class TriangleDrawAdapter : public IDrawStrategy, private Triangle
{
public:
virtual void draw() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void TriangleDrawAdapter::draw() const
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class CircleDrawAdapter : public IDrawStrategy, private Circle
{
public:
virtual void draw() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void CircleDrawAdapter::draw() const
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class SquareDrawAdapter : public IDrawStrategy, private Square
{
public:
virtual void draw() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void SquareDrawAdapter::draw() const
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Grapher grapher(&TriangleDrawAdapter());
grapher.drawShape();
grapher.setShape(&CircleDrawAdapter());
grapher.drawShape();
grapher.setShape(&SquareDrawAdapter());
grapher.drawShape();
}
C#
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Class.cs
Compiler : Visual Studio 2005 / C# 2.0
Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
Release : 07/11/2007 1.0
*/
using System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface IDrawStrategy
{
void draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Grapher
{
protected IDrawStrategy _drawStrategy = null;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Grapher()
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Grapher(IDrawStrategy drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void drawShape()
{
if (_drawStrategy != null)
_drawStrategy.draw();
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void setShape(IDrawStrategy drawStrategy)
{
_drawStrategy = drawStrategy;
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface IPaint
{
void paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Triangle : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Triangle");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Circle : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Circle");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Square : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Square");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class TriangleDrawAdapter : Triangle, IDrawStrategy
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void draw()
{
paint();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class CircleDrawAdapter : Circle, IDrawStrategy
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void draw()
{
paint();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class SquareDrawAdapter : Square, IDrawStrategy
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void draw()
{
paint();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Client
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
static void Main()
{
Grapher grapher = new Grapher(new TriangleDrawAdapter());
grapher.drawShape();
grapher.setShape(new CircleDrawAdapter());
grapher.drawShape();
grapher.setShape(new SquareDrawAdapter());
grapher.drawShape();
}
}
C++/CLI
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Class.cpp
Compiler : Visual C++ 8.0 / C++/CLI
Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
Release : 07/12/2007 1.0
*/
#include "stdafx.h"
using namespace System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class IDrawStrategy
{
void draw();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Grapher
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher() : _drawStrategy(nullptr)
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher(IDrawStrategy^ drawStrategy) : _drawStrategy(drawStrategy)
{}
public:
void drawShape();
void setShape(IDrawStrategy^ drawStrategy);
protected:
IDrawStrategy^ _drawStrategy;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::drawShape()
{
if (_drawStrategy != nullptr)
_drawStrategy->draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::setShape(IDrawStrategy^ drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class IPaint
{
void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Triangle : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Triangle::paint()
{
Console::WriteLine("Draw Triangle");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Circle : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Circle::paint()
{
Console::WriteLine("Draw Circle");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Square : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Square::paint()
{
Console::WriteLine("Draw Square");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class TriangleDrawAdapter : public IDrawStrategy, public Triangle
{
public:
virtual void draw();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void TriangleDrawAdapter::draw()
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class CircleDrawAdapter : public IDrawStrategy, public Circle
{
public:
virtual void draw();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void CircleDrawAdapter::draw()
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class SquareDrawAdapter : public IDrawStrategy, public Square
{
public:
virtual void draw();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void SquareDrawAdapter::draw()
{
paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Grapher^ grapher = gcnew Grapher(gcnew TriangleDrawAdapter);
grapher->drawShape();
grapher->setShape(gcnew CircleDrawAdapter);
grapher->drawShape();
grapher->setShape(gcnew SquareDrawAdapter);
grapher->drawShape();
}
VB
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
'
'(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/None.gif)
'Filename : DP_AdpaterPattern_Strategy_Class.vb
'Compiler : VB 9
'Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
'Release : 07/12/2007 1.0
'
Imports System
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface IDrawStrategyInterface IDrawStrategy
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub draw()Sub draw()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class GrapherClass Grapher
Protected _drawStrategy As IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub New()Sub New(Optional ByRef drawStrategy As IDrawStrategy = Nothing)
_drawStrategy = drawStrategy
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub drawShape()Sub drawShape()
If _drawStrategy IsNot Nothing Then
_drawStrategy.draw()
End If
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub setShape()Sub setShape(ByRef drawStrategy As IDrawStrategy)
_drawStrategy = drawStrategy
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface IPaintInterface IPaint
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub paint()Sub paint()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class TriangleClass Triangle
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Triangle")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class CircleClass Circle
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Circle")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class SquareClass Square
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Square")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class TriangleDrawAdapterClass TriangleDrawAdapter
Inherits Triangle
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class CircleDrawAdapterClass CircleDrawAdapter
Inherits Circle
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class SquareDrawAdapterClass SquareDrawAdapter
Inherits Square
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class ClientClass Client
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Shared Sub Main()Sub Main()
Dim grapher As Grapher = New Grapher(New TriangleDrawAdapter())
grapher.drawShape()
![](/Images/OutliningIndicators/InBlock.gif)
grapher.setShape(New CircleDrawAdapter())
grapher.drawShape()
![](/Images/OutliningIndicators/InBlock.gif)
grapher.setShape(New SquareDrawAdapter())
grapher.drawShape()
End Sub
End Class
執行結果
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
![](/images/cnblogs_com/oomusou/dp_strategy_object_adapter.jpg)
ISO C++
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Object.cpp
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
Description : Demo how to use Strategy Pattern with Adapter Pattern (Object)
Release : 07/11/2007 1.0
*/
#include <iostream>
using namespace std;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class IDrawStrategy
{
public:
virtual void draw() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Grapher
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher(IDrawStrategy* drawStrategy = 0) : _drawStrategy(drawStrategy)
{}
public:
void drawShape() const;
void setShape(IDrawStrategy* drawStrategy);
protected:
IDrawStrategy* _drawStrategy;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::drawShape() const
{
if (_drawStrategy)
_drawStrategy->draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::setShape(IDrawStrategy* drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class IPaint
{
public:
virtual void paint() const = 0;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Triangle : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Triangle::paint() const
{
cout << "Draw Triangle" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Circle : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Circle::paint() const
{
cout << "Draw Circle" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Square : public IPaint
{
public:
void paint() const;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Square::paint() const
{
cout << "Draw Square" << endl;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class DrawAdapter : public IDrawStrategy
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
DrawAdapter(IPaint* adaptee = 0) : _adaptee(adaptee)
{}
virtual void draw() const;
protected:
IPaint* _adaptee;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void DrawAdapter::draw() const
{
_adaptee->paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Grapher grapher(&DrawAdapter(&Triangle()));
grapher.drawShape();
grapher.setShape(&DrawAdapter(&Circle()));
grapher.drawShape();
grapher.setShape(&DrawAdapter(&Square()));
grapher.drawShape();
}
C#
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Object.cs
Compiler : Visual Studio 2005 / Visual C# 2.0
Description : Demo how to use Strategy Pattern with Adapter Pattern (Object)
Release : 07/11/2007 1.0
*/
using System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface IDrawStrategy
{
void draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Grapher
{
protected IDrawStrategy _drawStrategy = null;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Grapher()
{}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Grapher(IDrawStrategy drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void drawShape()
{
if (_drawStrategy != null)
_drawStrategy.draw();
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void setShape(IDrawStrategy drawStrategy)
{
_drawStrategy = drawStrategy;
}
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface IPaint
{
void paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Triangle : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Triangle");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Circle : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Circle");
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Square : IPaint
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void paint()
{
Console.WriteLine("Draw Square");
}
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class DrawAdapter : IDrawStrategy
{
protected IPaint _adaptee = null;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public DrawAdapter()
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public DrawAdapter(IPaint adaptee)
{
_adaptee = adaptee;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void draw()
{
_adaptee.paint();
}
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
class Client
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
static void Main()
{
Grapher grapher = new Grapher(new DrawAdapter(new Triangle()));
grapher.drawShape();
grapher.setShape(new DrawAdapter(new Circle()));
grapher.drawShape();
grapher.setShape(new DrawAdapter(new Square()));
grapher.drawShape();
}
}
C++/CLI
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/InBlock.gif)
Filename : DP_AdpaterPattern_Strategy_Object.cpp
Compiler : Visual C++ 8.0 / C++/CLI
Description : Demo how to use Strategy Pattern with Adpater Pattern (Object)
Release : 07/12/2007 1.0
*/
#include "stdafx.h"
using namespace System;
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class IDrawStrategy
{
void draw();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Grapher
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher() : _drawStrategy(nullptr)
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Grapher(IDrawStrategy^ drawStrategy) : _drawStrategy(drawStrategy)
{}
public:
void drawShape();
void setShape(IDrawStrategy^ drawStrategy);
protected:
IDrawStrategy^ _drawStrategy;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::drawShape()
{
if (_drawStrategy != nullptr)
_drawStrategy->draw();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Grapher::setShape(IDrawStrategy^ drawStrategy)
{
_drawStrategy = drawStrategy;
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
interface class IPaint
{
void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Triangle : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Triangle::paint()
{
Console::WriteLine("Draw Triangle");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Circle : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Circle::paint()
{
Console::WriteLine("Draw Circle");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class Square : public IPaint
{
public:
virtual void paint();
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void Square::paint()
{
Console::WriteLine("Draw Square");
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
ref class DrawAdapter : public IDrawStrategy
{
public:
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
DrawAdapter() : _adaptee(nullptr)
{}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
DrawAdapter(IPaint^ adaptee) : _adaptee(adaptee)
{}
virtual void draw();
protected:
IPaint^ _adaptee;
};
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void DrawAdapter::draw()
{
_adaptee->paint();
}
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
int main()
{
Grapher^ grapher = gcnew Grapher(gcnew DrawAdapter(gcnew Triangle));
grapher->drawShape();
grapher->setShape(gcnew DrawAdapter(gcnew Circle));
grapher->drawShape();
grapher->setShape(gcnew DrawAdapter(gcnew Square));
grapher->drawShape();
}
VB
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
'
'(C) OOMusou 2007 http://oomusou.cnblogs.com
![](/Images/OutliningIndicators/None.gif)
'Filename : DP_AdpaterPattern_Strategy_Class.vb
'Compiler : VB 9
'Description : Demo how to use Strategy Pattern with Adapter Pattern (Class)
'Release : 07/12/2007 1.0
'
Imports System
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface IDrawStrategyInterface IDrawStrategy
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub draw()Sub draw()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class GrapherClass Grapher
Protected _drawStrategy As IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub New()Sub New(Optional ByRef drawStrategy As IDrawStrategy = Nothing)
_drawStrategy = drawStrategy
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub drawShape()Sub drawShape()
If _drawStrategy IsNot Nothing Then
_drawStrategy.draw()
End If
End Sub
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub setShape()Sub setShape(ByRef drawStrategy As IDrawStrategy)
_drawStrategy = drawStrategy
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Interface IPaintInterface IPaint
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Sub paint()Sub paint()
End Interface
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class TriangleClass Triangle
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Triangle")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class CircleClass Circle
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Circle")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class SquareClass Square
Implements IPaint
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub paint()Sub paint() Implements IPaint.paint
Console.WriteLine("Draw Square")
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class TriangleDrawAdapterClass TriangleDrawAdapter
Inherits Triangle
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class CircleDrawAdapterClass CircleDrawAdapter
Inherits Circle
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class SquareDrawAdapterClass SquareDrawAdapter
Inherits Square
Implements IDrawStrategy
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Public Sub draw()Sub draw() Implements IDrawStrategy.draw
Me.paint()
End Sub
End Class
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Class ClientClass Client
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Shared Sub Main()Sub Main()
Dim grapher As Grapher = New Grapher(New TriangleDrawAdapter())
grapher.drawShape()
![](/Images/OutliningIndicators/InBlock.gif)
grapher.setShape(New CircleDrawAdapter())
grapher.drawShape()
![](/Images/OutliningIndicators/InBlock.gif)
grapher.setShape(New SquareDrawAdapter())
grapher.drawShape()
End Sub
End Class
執行結果
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