Here is a simple example about how to use factory mode to generate different subclasses in CPlusPlus project.
Class:
RulerBase
|
- RulerA
|
- RulerB
RulerFactory:
class RulerFactory
{
//...
std::unordered_map<std::string, InstanceGenerator> m_Generators
The whole project is at the following part.
fac.hpp
#pragma once
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
class RulerBase {
public:
void print(){ std::cout << "This is Ruler Base." << std::endl; };
};
typedef RulerBase* (*InstanceGenerator)();
class RulerFactory
{
public:
RulerFactory(){}
~RulerFactory(){}
RulerBase* GenerateModule(std::string moduleType)
{
auto it = m_Generators.find( moduleType );
if( it != m_Generators.end() )
{
return it->second();
}
return nullptr;
}
bool RegisterGenerator(std::string moduleType, const InstanceGenerator& funcCreate)
{
return m_Generators.insert(std::make_pair(moduleType, funcCreate)).second;
}
static RulerFactory & GetInstance()
{
static RulerFactory instance;
return instance;
}
private:
std::unordered_map<std::string, InstanceGenerator> m_Generators;
};
#define RULER_FACTORY_REGISTER(RulerClass, RulerClassStr) \
namespace RulerFactoryRegistrations { \
RulerFactoryRegistrations<RulerClass> obj##RulerClass(RulerClassStr); \
}
namespace RulerFactoryRegistrations {
template <typename T>
class RulerFactoryRegistrations
{
public:
RulerFactoryRegistrations(std::string type)
{
RulerFactory::GetInstance().RegisterGenerator(
type,
[]() { return static_cast<RulerBase*>(new T()); }
);
}
};
}
main.cpp
#include <iostream>
#include <map>
#include <string>
#include <memory>
#include <unordered_map>
#include "fac.hpp"
class RulerA : public RulerBase {
public:
void print() { std::cout << "This is RulerA." << std::endl; }
};
class RulerB : public RulerBase {
public:
void print() { std::cout << "This is RulerB." << std::endl; }
};
// register in manager
RULER_FACTORY_REGISTER( RulerA, "RulerA" );
RULER_FACTORY_REGISTER( RulerB, "RulerB" );
int main() {
// generate rulers from strings in json.
RulerA *objA = static_cast<RulerA *>( RulerFactory::GetInstance().GenerateModule( "RulerA" ) );
RulerB *objB = static_cast<RulerB *>( RulerFactory::GetInstance().GenerateModule( "RulerB" ) );
if (objA) {
objA->print();
}
if (objB) {
objB->print();
}
return 0;
}
Build and run it.
➜ g++ main.cpp fac.hpp
➜ ./a.out
This is RulerA.
This is RulerB.