Фабричный метод - это т.н. виртуальный конструктор. Внутри функции не должно быть конструкций выбора. Сам фабричный метод передается в другое место для порождения объектов некоторого класса с определенным интерфейсом.
Конструкции выбора обычно присутствуют внутри абстрактных фабрик. В фабрику приходит некий идентификатор типа и (если идентификатор определен) фабрика создает объект некоторого класса с определенным интерфейсом.
Абстрактную фабрику можно реализовать на основе контейнера фабричных методов. Шаблоны C++ и стандарты C++11/14 нам в этом только помогут. Самый простой код такой фабрики может выглядеть вот так:
Пример фабрикиtemplate< typename TInterface, typename... TArguments >
class AbstractFactory final
{
public:
// Produce the implementation, but return the pointer to interface.
inline std::shared_ptr<TInterface> Produce( const std::string& implementation_name, TArguments... arguments )
{
auto found_function = m_factory_functions.find( implementation_name );
return ( found_function == m_factory_functions.end() )? std::shared_ptr<TInterface>{} : found_function->second( std::forward<TArguments>( arguments )... );
};
// Define the implementation.
template< typename TImplementation >
inline const bool DefineImplementation()
{
return DefineImplementation<TImplementation>( TImplementation::ClassName() );
};
// Define the implementation.
template< typename TImplementation >
inline const bool DefineImplementation( const std::string& implementation_name )
{
// Abort the incorrect registration.
static_assert( std::is_base_of<TInterface, TImplementation>::value, "Implementation may only be derived from interface of Factory." );
auto found_function = m_factory_functions.find( implementation_name );
if( found_function == m_factory_functions.end() )
{
m_factory_functions[ implementation_name ] = &AbstractFactory<TInterface, TArguments...>::template ConstructImplementation<TImplementation>;
return true;
};
return false;
};
// Check the implementation name is already defined.
inline const bool IsImplementationDefined( const std::string& implementation_name ) const
{
return m_factory_functions.find( implementation_name ) != m_factory_functions.end();
};
private:
// The factory function just produce implementation.
template< typename TImplementation >
static std::shared_ptr<TInterface> ConstructImplementation( TArguments... arguments )
{
return std::static_pointer_cast<TInterface>(
std::make_shared<TImplementation>( std::forward<TArguments>( arguments )... )
);
};
private:
// Factory function produces the implementations of TInterface.
using FactoryFunction = std::shared_ptr<TInterface> (*)( TArguments... arguments );
std::unordered_map<std::string, FactoryFunction> m_factory_functions;
};
Работает она примерно так:
cpp.sh/93obm