2013-03-18 43 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