Я пытаюсь создать абстрактный шаблон фабрики, где у меня есть две фабрики, давайте назовем их factoryA и factoryB.Я буду использовать struct вместо класса, чтобы сохранить некоторую типизацию.
Для некоторого семейства унаследованных классов давайте начнем с некоторого класса A,
struct A
{
// ...
};
struct derivedA1 : public A
{
// ...
};
struct derivedA2 : public derivedA1
{
// ...
};
Теперь позвольте, в целях иллюстрации, сделатьто же самое с другим классом B.
struct B
{
// ...
};
struct derivedB1 : public B
{
// ...
};
struct derivedB2 : public derivedB1
{
// ...
};
Так что для этих классов я пытаюсь создать шаблон фабрики как таковой (заметьте, на моей работе мы используем собственную обработку ошибок, я буду вызывать error_handle_t, реализация которой должнане имеет значения):
struct factoryA
{
std::map<int, std::shared_ptr<A> > myMap;
factoryA()
{
// setup values to search against
myMap[0] = std::make_shared<A>();
myMap[1] = std::make_shared<derivedA1>();
myMap[2] = std::make_shared<derivedA2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
object = myMap[key];
return ...
}
};
struct factoryB
{
std::map<int, std::shared_ptr<B> > myMap;
factoryB()
{
// setup values to search against
myMap[0] = std::make_shared<B>();
myMap[1] = std::make_shared<derivedB1>();
myMap[2] = std::make_shared<derivedB2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<B>& object)
{
object = myMap[key];
return ...
}
};
Казалось бы, абстрактный интерфейсный класс мог бы быть подходящим базовым классом, но возвращаемые типы различны для каждой фабрики.И у классов A и B нет общего базового класса между ними, чтобы сделать эту работу «красиво», поэтому я не могу сделать
error_handle_t make_object(int key, std::shared_ptr<base_for_A_and_B>& object) = 0;
, но вышеперечисленные фабрики кажутся довольно стандартными и могут быть почтипараметризовано так:
template <typename T>
struct base
{
std::map<int, std::shared_ptr<T> > myMap;
error_handle_t make_object(int key, std::shared_ptr<T>& object)
{
object = myMap[key];
return ...
}
};
Согласно Переопределить член шаблона в интерфейсе , я не могу сделать класс шаблона виртуальным, чтобы он был абстрактным классом.
Ноесли мы можем предположить, что «алгоритм» make_object такой же.Я читал в Интернете, что это может быть служебный класс, такой, что
struct factoryA : private base<A>
{
std::map<int, std::shared_ptr<A> > myMap;
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
...
object = myMap[key];
return ...
}
};
Но я не переопределяю базу шаблонов, а просто использую ее как вспомогательную функцию.На самом деле не решает, чего я хочу достичь.
Конечная цель состояла в том, чтобы создать абстрактную фабрику, такую, чтобы
struct factories
{
template <typename T>
error_handle_t create(int key, shared_ptr<T>& object)
{
object = make_shared<T>()->make_object(key)
return ...;
}
};
вместо создания того же объекта без общего базового класса.
struct factories
{
// Initialize in ctor which I didn't include here
factoryA concrete_factoryA;
factoryB concrete_factoryB;
error_handle_t createA(int key, shared_ptr<A>& object)
{
object = concrete_factoryA.make_object(key);
return ...;
}
error_handle_t createB(int key, shared_ptr<B>& object)
{
object = concrete_factoryB.make_object(key);
return ...;
}
};
Итак, я должен создать метод create столько фабрик, сколько он содержит, без шаблонов рычагов и выводов типа каким-то чистым способом.Мысли или рекомендации?
использование, которое я хотел:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.create(0, a_ptr);
l_factories.create(1, b_ptr);
против того, что у меня есть:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.createA(0, a_ptr);
l_factories.createB(1, b_ptr);