design pattern - factory pattern in c++ and lua
![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Factory_Method_pattern_in_LePUS3.png/300px-Factory_Method_pattern_in_LePUS3.png)
In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be “new”. More broadly, a subroutine that returns a “new” object may be referred to as a “factory”, as in factory method or factory function. This is a basic concept in OOP, and forms the basis for a number of related software design patterns.
一一一一一一一一一一一一一一一一一一一一一一一一
© Hung-Chi's Blog
https://hungchicheng.github.io/2017/12/07/Design-Patterns-Factory-Pattern-in-lua-and-C++/
一一一一一一一一一一一一一一一一一一一一一一一一
What is Factory Pattern
Example in C++
#include <iostream>
#include <unordered_map>
#include <functional>
#include <vector>
// Base
class Monster {
public:
virtual void appear() = 0;
};
// Factory
class MonsterFactory {
public:
typedef std::unordered_map<std::string, std::function<Monster*()>> registry_map;
<span class="c1">// use this to instantiate the proper Derived class
static Monster * instantiate(const std::string& name)
{
auto it = MonsterFactory::registry().find(name);
return it == MonsterFactory::registry().end() ? nullptr : (it->second)();
}
<span class="k">static</span> <span class="n">registry_map</span> <span class="o">&</span> <span class="n">registry</span><span class="p">(){</span>
<span class="k">static</span> <span class="n">registry_map</span> <span class="n">impl</span><span class="p">;</span>
<span class="k">return</span> <span class="n">impl</span><span class="p">;</span>
<span class="p">}</span>
};
template<typename T> struct MonsterFactoryRegister
{
MonsterFactoryRegister(std::string name)
{
MonsterFactory::registry()[name] = { return new T; };
std::cout << "Registering class '" << name << "'n";
}
};
//------------------
class Ogre : public Monster {
public:
void appear() { std::cout << "appearing an Ogre " <<std::endl; }
private:
static MonsterFactoryRegister<Ogre> AddToFactory_;
};
MonsterFactoryRegister<Ogre> Ogre::AddToFactory_("Ogre" );
//------------------
class Demon : public Monster {
public:
void appear() { std::cout << "appearing a Demon " <<std::endl; }
private:
static MonsterFactoryRegister<Demon> AddToFactory_;
};
MonsterFactoryRegister<Demon> Demon::AddToFactory_("Demon" );
//------------------
class Troll : public Monster {
public:
void appear() { std::cout << "appearing a Troll " <<std::endl; }
private:
static MonsterFactoryRegister<Troll> AddToFactory_;
};
MonsterFactoryRegister<Troll> Troll::AddToFactory_("Troll" );
//------------------
int main(int argc, char argv[])
{
std::vector<Monster> Monsters;
<span class="n">Monsters</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span> <span class="n">MonsterFactory</span><span class="o">::</span><span class="n">instantiate</span><span class="p">(</span><span class="s">"Ogre"</span><span class="p">)</span> <span class="p">);</span>
<span class="n">Monsters</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span> <span class="n">MonsterFactory</span><span class="o">::</span><span class="n">instantiate</span><span class="p">(</span><span class="s">"Demon"</span><span class="p">)</span> <span class="p">);</span>
<span class="n">Monsters</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span> <span class="n">MonsterFactory</span><span class="o">::</span><span class="n">instantiate</span><span class="p">(</span><span class="s">"Troll"</span><span class="p">)</span> <span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&</span> <span class="n">Monster</span><span class="o">:</span> <span class="n">Monsters</span><span class="p">){</span>
<span class="n">Monster</span><span class="o">-></span><span class="n">appear</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
}
Output:
Registering class 'Ogre'
Registering class 'Demon'
Registering class 'Troll'
appearing an Ogre
appearing a Demon
appearing a Troll
appearing a Troll
Program ended with exit code: 0
Example in Lua
function FuncNew( obj ) -- for Inheritance
function obj:new( o )
o = o or {}
setmetatable( o, self )
self.__index = self
return o
end
return obj
end
–
Monster = {}
function Monster:create()
return FuncNew( Monster ):new()
end
function Monster:appear() – virtual
– do nothing
end
–
Ogre = Monster:create() – inheritance Monster
Ogre.name = "Ogre"
function Ogre:create()
return FuncNew( Ogre ):new()
end
function Ogre:appear() – override
print( "appearing an " … Ogre.name )
end
Demon = Monster:create() – inheritance Monster
Demon.name = "Demon"
function Demon:create()
return FuncNew( Demon ):new()
end
function Demon:appear() – override
print( "appearing a " … Demon.name )
end
Troll = Monster:create() – inheritance Monster
Troll.name = "Troll"
function Troll:create()
return FuncNew( Troll ):new()
end
function Troll:appear() – override
print( "appearing a " … Troll.name )
end
–
MonsterFactory = {}
MonsterFactory.registryTable = {}
function MonsterFactory:create()
return MonsterFactory
end
function MonsterFactory:instantiate( name )
for k,v in pairs(self.registryTable) do
if v.name == name then
return v:create()
end
end
return nil
end
function MonsterFactory:registry( monster )
print( "Registering class '" … monster.name … "'" )
table.insert( self.registryTable, monster )
end
–
MonsterFactory:registry( Ogre )
MonsterFactory:registry( Demon )
MonsterFactory:registry( Troll )
------------------------------------------------------
local monsters = {}
table.insert( monsters, MonsterFactory:instantiate( "Ogre" ) )
table.insert( monsters, MonsterFactory:instantiate( "Demon" ) )
table.insert( monsters, MonsterFactory:instantiate( "Troll" ) )
for k,v in pairs(monsters) do
v:appear()
end
Output:
Registering class 'Ogre'
Registering class 'Demon'
Registering class 'Troll'
appearing an Ogre
appearing a Demon
appearing a Troll
[Finished in 0.0s]