使用数组的C ++ Decorator模式实现

时间:2013-03-18 17:27:24

标签: c++ design-patterns implementation decorator

我在C ++中实现了Decorator模式,如下所示:

#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;
      }
   }

有没有可以避免复制的解决方案?

1 个答案:

答案 0 :(得分:0)

我会在for_each_element中实施Array,并在IArray中公开该界面。它有2个重载,需要std::function< void(T const&) >std::function< void(T) >(第二个是可选的)。现在PrintArray是一行lambda函数。

在C ++ 03中,您可以使用boost::function,而PrintArray更难以编写。所以这里不太诱人。

作为另一种方法,将const_iterator公开给底层数据。

顺便说一下,deque的表现令人惊讶地差。到目前为止,您的代码中没有任何内容会让我觉得您无法使用std::vector。如果您保证了内存连续性,您甚至可以让const_iteratorT const*并直接从IArray公开接口(使用Array中的实现)。 for_each_element在C ++ 11中变为双线,PrintArray即使没有C ++ 11或for_each_element也是2行,并且在IArray中内联实现或者一个自由的功能。

哦,我让PrintArray成为自由函数而不是成员函数。 for_each_element可能需要是成员函数,但是一旦公开迭代器和/或PrintArray,您就应该能够for_each_element无法访问私有数据。