C++設計模式-Adapter

來源:互聯網
上載者:User

一、功能

 

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

  二、結構圖

  (1)class adapter

  (2)object adapter

     三、實現

  和其他很多模式一樣,學習設計模式的重點是學習每種模式的思想,而不應拘泥於它的某種具體結構圖和實現。因為模式是靈活的,其實現可以是千變萬化的,只是所謂萬變不離其宗。 在STL中大量運用了Adapter模式,象function adapter、iterator adpter,它們與這裡說的adapter結構並不一樣,但思想是一樣的。具體的介紹可到侯捷網站上找相關文章,他講得非常好。

  四、範例程式碼

  (1)class adapter

namespace DesignPattern_Adapter
{
// class Adaptee
class Adaptee
{
public:
void SpecialRequest() {}
} ;

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

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

用戶端代碼:
{
using namespace DesignPattern_Adapter ;
Target *p = new Adapter() ;
p->Request() ; //實際上調用的是Adaptee::SpecialRequest()
}

 

(2)object adapter namespace DesignPattern_Adapter

 

{
// class Adaptee
class Adaptee
{
public:
void SpecialRequest() {}
} ;

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

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

用戶端代碼:
{
using namespace DesignPattern_Adapter ;
Target *p = new Adapter() ;
p->Request() ; //實際上調用的是Adaptee::SpecialRequest()
}

 

  六、執行個體

  (1)STL中的Class Adapter

  STL中的Adapter Class包括:a.stack(對應的adaptee是deque)。b.queue(對應的adaptee是deque)。c.priority_queue(對應的adaptee是vector)。 下面是從VC中的< stack >拷出的stack的類定義:

templateclass _Container = deque<_Ty> >
class stack
{ // LIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;

stack()
: c()
{ // construct with empty container
}

explicit stack(const _Container& _Cont)
: c(_Cont)
{ // construct by copying specified container
}

bool empty() const
{ // test if stack is empty
return (c.empty());
}

size_type size() const
{ // test length of stack
return (c.size());
}

value_type& top()
{ // return last element of mutable stack
return (c.back());
}

const value_type& top() const
{ // return last element of nonmutable stack
return (c.back());
}

void push(const value_type& _Val)
{ // insert element at end
c.push_back(_Val);
}

void pop()
{ // erase last element
c.pop_back();
}

bool _Eq(const stack<_Ty, _Container>& _Right) const
{ // test for stack equality
return (c == _Right.c);
}

bool _Lt(const stack<_Ty, _Container>& _Right) const
{ // test if this < _Right for stacks
return (c < _Right.c);
}

protected:
_Container c; // the underlying container
};

 

  關鍵之處在於_Container c,stack所有的操作都轉交給c去處理了。(這實際上就是前面所說的"object adapter",注意STL中的class adapter與上面所說的class adapter概念不完全一致)
stack的使用方法很簡單,如下:

 

{
int ia[] = { 1,3,2,4 };
deque id(ia, ia+4);
stack is(id);
}

 

  (2)近日看了一篇文章“Generic< Programming >:簡化異常安全的程式碼”,原文出自http://www.cuj.com/experts/1812/alexandr.htm?topic=experts, 中文譯文出自"C++ View第5期"。 文章絕對一流,作者給出的代碼中也使用了Adaptor模式,也有一定代表性。我將其問題一般化,概括出以下樣本:

 

  問題:假設有幾個已有類,他們有某些共同的行為,但它們彼此間是獨立的(沒有共同的基類)。如:

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

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

// ...

  如何以統一的方式去調用這些行為呢?

 

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

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

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

 

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

// class IAdaptor,抽象基類
class IAdaptor
{
public:
virtual void Proc() = 0 ;
} ;
// class Adaptor
template <class T>
class Adaptor : public IAdaptor, private T //實現繼承
{
public:
virtual void Proc() { T::Proc() ; }
} ;
// 以統一方式調用函數Proc,而不關心是T1、T2或其他什麼類
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 //實現繼承
{
public:
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() ;

 

  上面是樣本而非執行個體,你也許更願意看看它實際的運用。去下載作者所寫的代碼,好好欣賞一下吧。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.