Фабрика объектов регистрация шаблонной иерархии классов - PullRequest
0 голосов
/ 02 мая 2018

Я реализовал общую фабрику объектов, следуя указаниям книги Андрея Александреску Современный дизайн C ++ , поэтому я могу определить иерархию классов следующим образом (я напишу код наиболее упрощенным способом, избегая деталей реализации) или вопросы выделения / освобождения памяти; я знаю об этом, и я хотел бы сосредоточить обсуждение на основной проблеме):

// File "base.h"
#include <string>
#include "singleton.h"
#include "object_factory.h"
class Base;

using SingletonBaseFactory = Singleton
<
     ObjectFactory
     <
         Base,         // Abstract product type
         std::string,  // Identifier type
         Base* (*)()   // Concrete product creator type
     >
>;

class Base {
    // Define the interface (virtual functions, virtual dtor)
public:
    // Wrap the Factory method
    static Base* Factory(const std::string& ID) {
        return SingletonBaseFactory::Instance().Factory(ID);
    }
};

// File "derived_1.h"
#include "base.h"
class Derived_1 : public Base { /* ... */ };

// File "derived_2.h"
#include "base.h"
class Derived_2 : public Base { /* ... */ };

и зарегистрируйте каждый производный класс в анонимном пространстве имен в соответствующем файле реализации:

// File "derived_1.cpp"
#include "derived_1.h"
namespace {
    Base* CreateDerived_1() {
        return new Derived_1;
    }

    const bool registered = SingletonBaseFactory::Instance().Register("Derived_1", CreateDerived_1);
}

// Same for Derived_2 in file "derived_2.cpp"

Следовательно, пользователь, который хочет использовать эту иерархию в своем коде, должен просто вызвать метод Base::Factory с правильным идентификатором:

// File main.cpp
#include"base.h"
int main(){
    Base* pb = Base::Factory("Derived_1");

    // Do stuff with pb

    return 0;
}

Теперь предположим, что у меня есть иерархия классов шаблонов, скажем:

// File "baset.h"
#include <string>
#include "singleton.h"
#include "object_factory.h"

template<class T>
class BaseT;

template<class T>
using SingletonBaseTFactory = Singleton
<
    ObjectFactory
    <
        BaseT<T>,         // Abstract product type
        std::string,      // Identifier type
        BaseT<T>* (*)()   // Concrete product creator type
    >
>;

template<class T>
class BaseT {
    /*Define the interface*/ 
public:
    BaseT Factory(const std::string& ID) {
        return SingletonBaseTFactory<T>::Instance().Factory(ID);
    }
};

// File "derivedt_1.h"
#include "baset.h"
template<class T>
class DerivedT_1 : public BaseT<T> { /* ... */ };

В этом случае регистрация является обязанностью пользователя для каждого типа T, который он хочет использовать, перед использованием иерархии классов:

// File main.cpp
#include "baset.h"
#include "derivedt_1.h"

bool register_derived_1_int = SingletonBaseTFactory<int>::Instance().Register("Derived_1", [](){ return new DerivedT_1<int>; });

int main() {
    BaseT<int>* pb = BaseT<int>::Factory("Derived_1");
    return 0;
}

Имея в виду, что идентификатор каждого производного шаблонного класса одинаков для каждого типа T, имело бы ли смысл делегировать ответственность за регистрацию разработчику каждого производного класса (а не пользователю) даже в шаблонной форме? дело? Если да, то есть ли обходной путь для его достижения?

EDIT:

Я нашел эту работу https://www.artima.com/cppsource/subscription_problem.html, которая решает проблему регистрации фабрики объектов в шаблонном случае. Однако за регистрацию производных классов все еще отвечает тот, кто знает тип (типы), с которыми может быть создан производный класс. Как правило, у разработчика классов нет такого знания - у пользователя оно есть. Итак, опять же, есть ли способ отстранить пользователя от ответственности за регистрацию производного класса?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...