Answer the question
In order to leave comments, you need to log in
How to implement factory method without switch?
How can you implement the "factory method" design pattern without using switch / multiple if / separate factories?
Answer the question
In order to leave comments, you need to log in
The factory method is the so-called. virtual constructor. There should be no choice constructs inside a function. The factory method itself is passed elsewhere to produce objects of some class with a particular interface.
Choice constructs are usually present inside abstract factories. A certain type identifier comes to the factory and (if the identifier is defined) the factory creates an object of some class with a certain interface.
An abstract factory can be implemented based on a container of factory methods. C++ templates and C++11/14 standards will only help us with this. The simplest code for such a factory might look like this:
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;
};
You answered your own question - factory method. The description and implementation of this pattern is available for all wiki
languages
. As for the "separate factories", it's not entirely clear. The pattern itself abstracts the logic behind the decision to create an object. This logic is based on some kind of condition: switch / several if / separate factories. How you wrap this condition is your choice.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question