C++ 設計模式之Adaptor

一、Adapter功能

將一個類的接口(待匹配接口)轉換成客戶希望的另外一個接口(目標接口),解決兩個已有接口之間不匹配的問題。Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。

實質上過程是adaptee(待匹配類)---->adapter(匹配類)---->target(模板類),target類中的接口才是客戶希望要的接口。

二、結構圖

Adapter有兩種模式:class adapter和object adapter,筆者翻譯爲類匹配和對象匹配;

class adapter

object adapter


圖中的Client、Target、Adapter、Adaptee都表示類,裏面的都是方法接口,特別三角符號表示繼承關係。

三、示例代碼

class adapter

// 待匹配的接口
class Adaptee
{
public:
void SpecialRequest() {};
} ;
// 目標接口,靠匹配類去實現目標的接口
class Target
{
public:
virtual void Request() = 0 ;
} ;
// 匹配類,實現目標接口,並通過繼承方式調用父類接口的方式去匹配Adaptee接口
class Adapter : public Target, private Adaptee
{
public:
virtual void Request(){SpecialRequest() ; }
} ;

客戶端代碼:
Target *p = new Adapter() ;
p->Request() ; //實際上調用的是Adaptee::SpecialRequest()
object adapter

// 待匹配的接口
class Adaptee

{
public:void SpecialRequest() {};
} ;

// 目標接口,靠匹配類去實現目標的接口</span>

class Target
{
public:virtual void Request() = 0 ;
} ;

// 匹配類,實現目標接口,並通過調用待匹配類對象方法的方式去匹配Adaptee接口</span>

class Adapter : public Target
{
public:virtual void Request() 
{ 
_adaptee.SpecialRequest() ; 
}
private:Adaptee _adaptee ;
} ;

客戶端代碼:

Target *p = new Adapter() ;p->Request() ; //實際上調用的是Adaptee::SpecialRequest()


四、應用拓展

問題:假設有幾個已有類,他們有某些共同的行爲,但它們彼此間是獨立的(沒有共同的基類)。如何以統一的方式去調用這些行爲呢? 

class T1
{
public:
void Proc() {}
} ;
class T2
{
public:
void Proc() {}
} ;
// ...

解決方法1:很自然的會想到用模板,如:

template <class T>
void Test(T t)
{
t.Proc() ;
}

這隻適用於簡單的情況,有時情況是很複雜的,比如我們無法把類型放到模板參數中!

解決方法2:困難來自於這些類沒有共同的基類,所以我們就創造一個基類,然後再Adapter。

//我們抽象出來的基類
class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ; 
//匹配類
template <class T>
class Adaptor : public IAdaptor, private T //實現繼承,T爲上面的T1或則T2
{
public:
virtual void Proc() { T::Proc() ; }
} ;
// 以統一方式調用函數Proc,而不關心是T1、T2或其他什麼類,因爲他們都有Prop()

class Target

{
void Test(const std::auto_ptr& sp)

{
sp->Proc() ;
}

}
客戶端代碼:
Test(std::auto_ptr(new Adaptor)) ;
Test(std::auto_ptr(new Adaptor)) ;

上例很簡單,用方法一中的模板函數就可以很好地解決了。下面是一個略微複雜一點的例子,根據參數類型來創建適當的對象:

class T1
{
public:
T1(int) { }
void Proc() { }
} ;

class T2
{
public:
T2(char) { }
void Proc() { }
} ;

// class IAdaptor,抽象基類
class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;

// class Adaptor
template 
class Adaptor : public IAdaptor, private T //實現繼承,T爲T1或者T2
{
public:

//兩種構造函數,並根據參數類型不同去實例化不同的T
Adaptor(int n) : T(n) {}
Adaptor(char c) : T(c) {}
virtual void Proc() { T::Proc() ; }
} ;

class Test
{
public:
Test(int n) : sp(new Adaptor(n)) {}
Test(char c) : sp(new Adaptor(c)) {}

void Proc() { sp->Proc() ; }
private:
std::auto_ptr sp ;
} ;

客戶端代碼:
Test t1(10) ;
t1.Proc() ;

Test t2('c') ;
t2.Proc() ;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章