2013-03-18 58 views
0

我已經實現Decorator模式在C++如下:C++裝飾模式實現使用數組

#include <iostream> 
#include <string> 
#include <deque> 
using namespace std; 

// Abstract Component 
template <class T> 
class IArray 
{ 
public: 
    virtual void insert(const T&) = 0; 
    virtual ~IArray(){} 

}; 

// Concrete Component 
template <class T> 
class Array : public IArray<T> 
{ 
public: 
    virtual void insert(const T& elem) 
    { 
     m_array.push_back(elem); 
    } 

private: 
    deque<T> m_array; 
}; 

// Decorator 1 
template <class T> 
class PositiveArray : public IArray<T> 
{ 
public: 
    PositiveArray(IArray<T>* component):m_component(component) 
    { 

    } 

    virtual void insert(const T& elem) 
    { 
     if (elem > 0) 
     { 
     m_component->insert(elem); 
     } 
     else 
     { 
     cerr << "You can't insert non-positive number." <<endl; 
     } 
    } 
private: 
    IArray<T>* m_component; 
}; 


// Decorator 2 
template <class T> 
class PrintArray : public IArray<T> 
{ 
public: 
    PrintArray(IArray<T>* component):m_component(component) 
    { 

    } 

    virtual void insert(const T& elem) 
    { 
     m_component->insert(elem); 
     cout << "Element " << elem << " was inserted into the array." <<endl; 
    } 
private: 
    IArray<T>* m_component; 
}; 

// Client 
int main() 
{ 
    typedef int MyType; 

    PositiveArray<MyType> arr(new PrintArray<MyType>(new Array<MyType>)); 
    arr.insert(10); 
    arr.insert(-10); 

    int i; 
    cin>>i; 
    return 0; 
} 

現在我想爲所有陣列printArray功能。我應該將它作爲IArray中的純虛擬函數編寫,並將該函數的以下實現複製到IArray的每個子進程中?

void printArray() 
    { 
     for (int i = 0; i < m_array.size(); ++i) 
     { 
     cout << "elem " <<i << " is " << m_array[i] <<endl; 
     } 
    } 

有沒有可以避免複製的解決方案?

回答

0

我會在Array中執行for_each_element,並在IArray中公開接口。它有2個過載,採取std::function< void(T const&) >std::function< void(T) >(第二個是可選的)。現在PrintArray是一個單行lambda函數。

在C++ 03中,您可以使用boost::function,而PrintArray更令人討厭寫入。所以這裏不那麼誘人。

作爲另一種方法,將const_iterator公開給底層數據。

另外,deque的表現令人驚訝的差。到目前爲止,你的代碼中沒有任何東西會讓我認爲你不能使用std::vector。如果你保證了內存連續性,你甚至可以讓你的版本號爲T const*,並直接從IArray(在Array的實現中)公開接口。 for_each_element成爲C++ 11中的雙線程,並且即使沒有C++ 11或for_each_element,也是PrintArray是2行,並且可以在IArray中內聯執行,也可以作爲自由函數實現。

哦,我會讓PrintArray一個自由功能,而不是一個成員函數。 for_each_element可能需要成爲成員函數,但是一旦您公開迭代器和/或for_each_element,您應該可以在不訪問私有數據的情況下PrintArray

+0

您可以使用舊的C++標準編寫解決方案的代碼嗎? – Narek 2013-03-18 17:39:34

+0

哪個解決方案? 'std :: vector'和'typedef T const * const_iterator'和'virtual const_iterator begin()'很容易用C++ 03編寫,而且速度會很快。在C++ 03中使用'for_each_element'會比C++ 11糟糕,但你可以通過手動函數或者一些boost庫(lambda,phoenix等)來實現。 03年,我很想說我的數組保證是連續的,並使用'typedef const T * const_iterator'。 – Yakk 2013-03-18 18:08:32