// factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include <map>
#include <utility>
// pluggable factories
template <class Object, class Param, class ID>
class Factory
{
public:
virtual ~Factory();
static Object* newObject(Param param);
protected:
Factory(ID id);
static ID GetID(Param param); // must be implemented separately
virtual Object* makeObject(Param param) const = 0;
private:
typedef Factory<Object, Param, ID>* MakerPtr;
typedef std::map<ID, MakerPtr> MakerMap;
static MakerMap st_registry;
};
template <class Object, class Param, class ID>
Object* Factory<Object, Param, ID>::newObject(Param param)
{
ID id = GetID(param);
typename MakerMap::const_iterator it = st_registry.find(id);
return it != st_registry.end()? it->second->makeObject(param) : 0;
};
template <class Object, class Param, class ID>
Factory<Object, Param, ID>::Factory(ID id)
{
std::pair<typename MakerMap::iterator, bool> p =
st_registry.insert(std::make_pair(id, this));
}
template <class Object, class Param, class ID>
Factory<Object, Param, ID>::~Factory()
{
}
template <class Object, class Param, class ID>
typename Factory<Object, Param, ID>::MakerMap Factory<Object, Param, ID>::st_registry;
// maker
template <class Object, class Base, class Param, class ID, ID id>
class Maker : public Factory<Base, Param, ID>
{
public:
Maker() : Factory<Base, Param, ID>(id)
{}
protected:
Object* makeObject(Param param) const
{
return new Object(param);
}
private:
static const Maker registerThis;
};
template <class Object, class Base, class Param, class ID, ID id>
const Maker<Object, Base, Param, ID, id> Maker<Object, Base, Param, ID, id>::registerThis;
#endif
// FactoryTest.cpp
//#include "factory.h"
#include <iostream>
class TestBase
{
public:
virtual void load() = 0;
};
class Test1 : public TestBase
{
public:
Test1(std::istream& is)
{}
void load()
{
std::cout << "loading Test1 data" << std::endl;
}
};
class Test2 : public TestBase
{
public:
Test2(std::istream& is)
{}
void load()
{
std::cout << "loading Test2 data" << std::endl;
}
};
typedef Factory<TestBase, std::istream&, int> TestFactory;
template<>
int TestFactory::GetID(std::istream& is)
{
int id = 0;
is >> id;
return id;
}
void FactoryTest()
{
// instantiate maker classes
static Maker<Test1, TestBase, std::istream&, int, 1> maker1;
static Maker<Test2, TestBase, std::istream&, int, 2> maker2;
TestBase *base = TestFactory::newObject(std::cin);
if (base)
base->load();
}
int main()
{
while (std::cin)
FactoryTest();
return 0;
}
Ly8gZmFjdG9yeS5oCiNpZm5kZWYgRkFDVE9SWV9ICiNkZWZpbmUgRkFDVE9SWV9ICgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8dXRpbGl0eT4KCi8vIHBsdWdnYWJsZSBmYWN0b3JpZXMKCnRlbXBsYXRlIDxjbGFzcyBPYmplY3QsIGNsYXNzIFBhcmFtLCBjbGFzcyBJRD4KY2xhc3MgRmFjdG9yeQp7CnB1YmxpYzoKCXZpcnR1YWwgfkZhY3RvcnkoKTsKCglzdGF0aWMgT2JqZWN0KiBuZXdPYmplY3QoUGFyYW0gcGFyYW0pOwoKcHJvdGVjdGVkOgoJRmFjdG9yeShJRCBpZCk7CgoJc3RhdGljIElEIEdldElEKFBhcmFtIHBhcmFtKTsgLy8gbXVzdCBiZSBpbXBsZW1lbnRlZCBzZXBhcmF0ZWx5CgoJdmlydHVhbCBPYmplY3QqIG1ha2VPYmplY3QoUGFyYW0gcGFyYW0pIGNvbnN0ID0gMDsKCnByaXZhdGU6Cgl0eXBlZGVmIEZhY3Rvcnk8T2JqZWN0LCBQYXJhbSwgSUQ+KiBNYWtlclB0cjsKCXR5cGVkZWYgc3RkOjptYXA8SUQsIE1ha2VyUHRyPiBNYWtlck1hcDsKCglzdGF0aWMgTWFrZXJNYXAgc3RfcmVnaXN0cnk7Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgT2JqZWN0LCBjbGFzcyBQYXJhbSwgY2xhc3MgSUQ+Ck9iamVjdCogRmFjdG9yeTxPYmplY3QsIFBhcmFtLCBJRD46Om5ld09iamVjdChQYXJhbSBwYXJhbSkKewoJSUQgaWQgPSBHZXRJRChwYXJhbSk7Cgl0eXBlbmFtZSBNYWtlck1hcDo6Y29uc3RfaXRlcmF0b3IgaXQgPSBzdF9yZWdpc3RyeS5maW5kKGlkKTsKCXJldHVybiBpdCAhPSBzdF9yZWdpc3RyeS5lbmQoKT8gaXQtPnNlY29uZC0+bWFrZU9iamVjdChwYXJhbSkgOiAwOwp9OwoKdGVtcGxhdGUgPGNsYXNzIE9iamVjdCwgY2xhc3MgUGFyYW0sIGNsYXNzIElEPgpGYWN0b3J5PE9iamVjdCwgUGFyYW0sIElEPjo6RmFjdG9yeShJRCBpZCkKewoJc3RkOjpwYWlyPHR5cGVuYW1lIE1ha2VyTWFwOjppdGVyYXRvciwgYm9vbD4gcCA9CgkgICAgc3RfcmVnaXN0cnkuaW5zZXJ0KHN0ZDo6bWFrZV9wYWlyKGlkLCB0aGlzKSk7Cn0KCnRlbXBsYXRlIDxjbGFzcyBPYmplY3QsIGNsYXNzIFBhcmFtLCBjbGFzcyBJRD4KRmFjdG9yeTxPYmplY3QsIFBhcmFtLCBJRD46On5GYWN0b3J5KCkKewp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgT2JqZWN0LCBjbGFzcyBQYXJhbSwgY2xhc3MgSUQ+CnR5cGVuYW1lIEZhY3Rvcnk8T2JqZWN0LCBQYXJhbSwgSUQ+OjpNYWtlck1hcCBGYWN0b3J5PE9iamVjdCwgUGFyYW0sIElEPjo6c3RfcmVnaXN0cnk7CgovLyBtYWtlcgoKdGVtcGxhdGUgPGNsYXNzIE9iamVjdCwgY2xhc3MgQmFzZSwgY2xhc3MgUGFyYW0sIGNsYXNzIElELCBJRCBpZD4KY2xhc3MgTWFrZXIgOiBwdWJsaWMgRmFjdG9yeTxCYXNlLCBQYXJhbSwgSUQ+CnsKcHVibGljOgoJTWFrZXIoKSA6IEZhY3Rvcnk8QmFzZSwgUGFyYW0sIElEPihpZCkKCXt9Cgpwcm90ZWN0ZWQ6CglPYmplY3QqIG1ha2VPYmplY3QoUGFyYW0gcGFyYW0pIGNvbnN0Cgl7CgkJcmV0dXJuIG5ldyBPYmplY3QocGFyYW0pOwoJfQoKcHJpdmF0ZToKCXN0YXRpYyBjb25zdCBNYWtlciByZWdpc3RlclRoaXM7Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgT2JqZWN0LCBjbGFzcyBCYXNlLCBjbGFzcyBQYXJhbSwgY2xhc3MgSUQsIElEIGlkPgpjb25zdCBNYWtlcjxPYmplY3QsIEJhc2UsIFBhcmFtLCBJRCwgaWQ+IE1ha2VyPE9iamVjdCwgQmFzZSwgUGFyYW0sIElELCBpZD46OnJlZ2lzdGVyVGhpczsKCiNlbmRpZgoKLy8gRmFjdG9yeVRlc3QuY3BwCi8vI2luY2x1ZGUgImZhY3RvcnkuaCIKI2luY2x1ZGUgPGlvc3RyZWFtPgoKY2xhc3MgVGVzdEJhc2UKewpwdWJsaWM6Cgl2aXJ0dWFsIHZvaWQgbG9hZCgpID0gMDsKfTsKCmNsYXNzIFRlc3QxIDogcHVibGljIFRlc3RCYXNlCnsKcHVibGljOgoJVGVzdDEoc3RkOjppc3RyZWFtJiBpcykKCXt9CgkKCXZvaWQgbG9hZCgpCgl7CgkJc3RkOjpjb3V0IDw8ICJsb2FkaW5nIFRlc3QxIGRhdGEiIDw8IHN0ZDo6ZW5kbDsKCX0KfTsKCmNsYXNzIFRlc3QyIDogcHVibGljIFRlc3RCYXNlCnsKcHVibGljOgoJVGVzdDIoc3RkOjppc3RyZWFtJiBpcykKCXt9CgkKCXZvaWQgbG9hZCgpCgl7CgkJc3RkOjpjb3V0IDw8ICJsb2FkaW5nIFRlc3QyIGRhdGEiIDw8IHN0ZDo6ZW5kbDsKCX0KfTsKCnR5cGVkZWYgRmFjdG9yeTxUZXN0QmFzZSwgc3RkOjppc3RyZWFtJiwgaW50PiBUZXN0RmFjdG9yeTsKCnRlbXBsYXRlPD4KaW50IFRlc3RGYWN0b3J5OjpHZXRJRChzdGQ6OmlzdHJlYW0mIGlzKQp7CglpbnQgaWQgPSAwOwoJaXMgPj4gaWQ7CglyZXR1cm4gaWQ7Cn0KCnZvaWQgRmFjdG9yeVRlc3QoKQp7CgkvLyBpbnN0YW50aWF0ZSBtYWtlciBjbGFzc2VzCglzdGF0aWMgTWFrZXI8VGVzdDEsIFRlc3RCYXNlLCBzdGQ6OmlzdHJlYW0mLCBpbnQsIDE+IG1ha2VyMTsKCXN0YXRpYyBNYWtlcjxUZXN0MiwgVGVzdEJhc2UsIHN0ZDo6aXN0cmVhbSYsIGludCwgMj4gbWFrZXIyOwoKCVRlc3RCYXNlICpiYXNlID0gVGVzdEZhY3Rvcnk6Om5ld09iamVjdChzdGQ6OmNpbik7CglpZiAoYmFzZSkKCQliYXNlLT5sb2FkKCk7Cn0KCmludCBtYWluKCkKewoJd2hpbGUgKHN0ZDo6Y2luKQoJICBGYWN0b3J5VGVzdCgpOwoJICAKCXJldHVybiAwOwp9