Давайте представим, что у нас есть несколько типов элементов, и мы хотим создать «менеджера» для каждого из них.Менеджер позаботится о создании, активации / деактивации и удалении любого из элементов (мы предполагаем, что пользователь не будет создавать / уничтожать экземпляры этих элементов без использования менеджера. Очень простой пример кода будет выглядеть примерно так::
template <class T>
class NonCachedElementMngr
{
public:
NonCachedElementMngr():
rmCounter(0)
{}
~ NonCachedElementMngr()
{
T* element = 0;
if(mElements.size() > 0)
{
typename std::set<T*>::iterator it;
for(it = mElements.begin(); it != mElements.end(); ++it)
{
element = *it;
element->deactivate();
delete element;
}
}
}
T* create()
{
T* element = new T();
element->activate();
mElements.insert(element);
return element;
}
bool release(T* element)
{
bool ret = false;
typename std::set<T*>::iterator it;
it = mElements.find(element);
if(it != mElements.end())
{
element->deactivate();
delete element;
mElements.erase(it);
ret = true;
}
return ret;
}
private:
std::set<T*> mElements;
int rmCounter;
};
Давайте теперь представим, что для подгруппы объектов, кроме основной операции, нам также необходимо выполнить некоторое кэширование. Для этой подгруппы типов мы могли бы определить другого «менеджера», например:
template <class T>
class CachedElementMngr
{
public:
CachedElementMngr():
rmCounter(0)
{}
~CachedElementMngr()
{
T* element = 0;
if(mElements.size() > 0)
{
typename std::set<T*>::iterator it;
for(it = mElements.begin(); it != mElements.end(); ++it)
{
element = *it;
element->removeFromCache(); // <<<<<<<<<<<<<< Different line
element->deactivate();
delete element;
}
}
}
T* create()
{
T* element = new T();
element->storeInCache(); // <<<<<<<<<<<<<< Different line
element->activate();
mElements.insert(element);
return element;
}
bool release(T* element)
{
bool ret = false;
typename std::set<T*>::iterator it;
it = mElements.find(element);
if(it != mElements.end())
{
element->removeFromCache(); // <<<<<<<<<<<<<< Different line
element->deactivate();
delete element;
mElements.erase(it);
ret = true;
}
return ret;
}
private:
std::set<T*> mElements;
int rmCounter;
};
Очевидно, что оба менеджера абсолютно одинаковы, за исключением трех строк, помеченных как таковые. Как я могу реорганизовать эти два шаблона?нет. Обратите внимание, что в деструкторе также есть другая строка. Любое возможное предложение (виртуальное наследование, специализация шаблона, SFINAE ...) будет очень приветствоваться.