Я реализовал шаблон Decorator в 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;
}
}
Есть ли какое-либо решение, которое можно избежать копирования?
Я бы реализовал for_each_element
в любом Array
и выставить интерфейс в IArray
, Он имеет 2 перегрузки, которые принимают std::function< void(T const&) >
а также std::function< void(T) >
(второй не обязателен). Сейчас PrintArray
является одной строкой лямбда-функции.
В C ++ 03 вы можете использовать boost::function
, а также PrintArray
больше раздражает писать. Так что здесь это менее заманчиво.
Как другой подход, разоблачить const_iterator
с базовыми данными.
Как в сторону, deque
производительность на удивление плохая. Пока что в вашем коде нет ничего, что заставило бы меня думать, что вы не можете использовать std::vector
, Если бы вы гарантировали непрерывность памяти, вы могли бы даже иметь const_iterator
должно быть T const*
и выставить интерфейс прямо из IArray
(с реализацией в Array
). for_each_element
становится двухслойным в C ++ 11, и PrintArray
даже без C ++ 11 или for_each_element
2 строки, и либо встроенные в IArray
или как бесплатная функция.
Ох, и я бы сделал PrintArray
свободная функция, а не функция-член. for_each_element
возможно, должна быть функция-член, но вы должны быть в состоянии PrintArray
без доступа к личным данным, как только вы выставите итераторы и / или for_each_element
,
Других решений пока нет …