fork(1) download
  1. // factory.h
  2. #ifndef FACTORY_H
  3. #define FACTORY_H
  4.  
  5. #include <map>
  6. #include <utility>
  7.  
  8. // pluggable factories
  9.  
  10. template <class Object, class Param, class ID>
  11. class Factory
  12. {
  13. public:
  14. virtual ~Factory();
  15.  
  16. static Object* newObject(Param param);
  17.  
  18. protected:
  19. Factory(ID id);
  20.  
  21. static ID GetID(Param param); // must be implemented separately
  22.  
  23. virtual Object* makeObject(Param param) const = 0;
  24.  
  25. private:
  26. typedef Factory<Object, Param, ID>* MakerPtr;
  27. typedef std::map<ID, MakerPtr> MakerMap;
  28.  
  29. static MakerMap st_registry;
  30. };
  31.  
  32. template <class Object, class Param, class ID>
  33. Object* Factory<Object, Param, ID>::newObject(Param param)
  34. {
  35. ID id = GetID(param);
  36. typename MakerMap::const_iterator it = st_registry.find(id);
  37. return it != st_registry.end()? it->second->makeObject(param) : 0;
  38. };
  39.  
  40. template <class Object, class Param, class ID>
  41. Factory<Object, Param, ID>::Factory(ID id)
  42. {
  43. std::pair<typename MakerMap::iterator, bool> p =
  44. st_registry.insert(std::make_pair(id, this));
  45. }
  46.  
  47. template <class Object, class Param, class ID>
  48. Factory<Object, Param, ID>::~Factory()
  49. {
  50. }
  51.  
  52. template <class Object, class Param, class ID>
  53. typename Factory<Object, Param, ID>::MakerMap Factory<Object, Param, ID>::st_registry;
  54.  
  55. // maker
  56.  
  57. template <class Object, class Base, class Param, class ID, ID id>
  58. class Maker : public Factory<Base, Param, ID>
  59. {
  60. public:
  61. Maker() : Factory<Base, Param, ID>(id)
  62. {}
  63.  
  64. protected:
  65. Object* makeObject(Param param) const
  66. {
  67. return new Object(param);
  68. }
  69.  
  70. private:
  71. static const Maker registerThis;
  72. };
  73.  
  74. template <class Object, class Base, class Param, class ID, ID id>
  75. const Maker<Object, Base, Param, ID, id> Maker<Object, Base, Param, ID, id>::registerThis;
  76.  
  77. #endif
  78.  
  79. // FactoryTest.cpp
  80. //#include "factory.h"
  81. #include <iostream>
  82.  
  83. class TestBase
  84. {
  85. public:
  86. virtual void load() = 0;
  87. };
  88.  
  89. class Test1 : public TestBase
  90. {
  91. public:
  92. Test1(std::istream& is)
  93. {}
  94.  
  95. void load()
  96. {
  97. std::cout << "loading Test1 data" << std::endl;
  98. }
  99. };
  100.  
  101. class Test2 : public TestBase
  102. {
  103. public:
  104. Test2(std::istream& is)
  105. {}
  106.  
  107. void load()
  108. {
  109. std::cout << "loading Test2 data" << std::endl;
  110. }
  111. };
  112.  
  113. typedef Factory<TestBase, std::istream&, int> TestFactory;
  114.  
  115. template<>
  116. int TestFactory::GetID(std::istream& is)
  117. {
  118. int id = 0;
  119. is >> id;
  120. return id;
  121. }
  122.  
  123. void FactoryTest()
  124. {
  125. // instantiate maker classes
  126. static Maker<Test1, TestBase, std::istream&, int, 1> maker1;
  127. static Maker<Test2, TestBase, std::istream&, int, 2> maker2;
  128.  
  129. TestBase *base = TestFactory::newObject(std::cin);
  130. if (base)
  131. base->load();
  132. }
  133.  
  134. int main()
  135. {
  136. while (std::cin)
  137. FactoryTest();
  138.  
  139. return 0;
  140. }
Success #stdin #stdout 0s 15240KB
stdin
1
2
stdout
loading Test1 data
loading Test2 data