fork download
  1. #include <list>
  2. #include <iostream>
  3.  
  4. // Bazowy kreator jak u Ciebie - nie musi w zasadzie byc szablonem.
  5. template <typename AbstractProduct>
  6. class CreatorBase {
  7. public:
  8. // Implementacja konstruktora ponizej.
  9. CreatorBase();
  10.  
  11. virtual AbstractProduct *create() = 0;
  12. };
  13.  
  14. // Klasa tworzaca te rozne klasy w taki sam sposob jak u Ciebie.
  15. // "Wadami" takiego rozwiazania jest to, ze instancje tej klasy musza istniec
  16. // przez caly czas dzialania programu. W poprzednim podejsciu mozna bylo sobie
  17. // rejestracje zrobic gdziekolwiek i kiedykolwiek.
  18. template <typename AbstractProduct, typename ConcreteProduct>
  19. class Creator : public CreatorBase<AbstractProduct> {
  20. public:
  21. Creator() {};
  22.  
  23. virtual AbstractProduct *create() { return new ConcreteProduct; }
  24. };
  25.  
  26. // Prosta fabryka korzystajca z kreatorow wyzej.
  27. // To jest singleton - to ten fakt rozwiazuje problemy kolejnosci statycznej
  28. // inicjalizacji. Niektorzy twierdza, ze singletony sa zle.
  29. // Jezeli bedziesz chcial uzywac tego w bibliotece wspoldzielonej
  30. // pojawi sie potrzeba uzywania extern templates, zeby wymusic jedna instancje.
  31. template <typename Product>
  32. class Factory {
  33. public:
  34. typedef std::list<CreatorBase<Product> *> RegisteredList;
  35. typedef typename RegisteredList::iterator iterator;
  36.  
  37. // Dostep do singletonu.
  38. static Factory &instance() {
  39. static Factory object;
  40. return object;
  41. }
  42.  
  43. void add(CreatorBase<Product> * creator) {
  44. mRegisteredList.push_back(creator);
  45. }
  46.  
  47. iterator begin() {
  48. return mRegisteredList.begin();
  49. }
  50.  
  51. iterator end() {
  52. return mRegisteredList.end();
  53. }
  54.  
  55. private:
  56. RegisteredList mRegisteredList;
  57.  
  58. // Prywatny konstruktor.
  59. Factory() {};
  60.  
  61. // A to jest wylaczone.
  62. Factory(const Factory &) = delete;
  63. Factory &operator=(const Factory &) = delete;
  64.  
  65. };
  66.  
  67. // Konstruktor CreatorBase musi byc tutaj z tego samego powodu co u Ciebie.
  68. // To mi sie troche nie podoba, ale chyba jednak nie ma w tym niczego zlego.
  69. template <typename AbstractProduct>
  70. CreatorBase<AbstractProduct>::CreatorBase() {
  71. Factory<AbstractProduct>::instance().add(this);
  72. }
  73.  
  74. // Ponizej jest w zasadzie skopiowany Twoj kod.
  75.  
  76. // Plik register.h
  77. class RegisteredBase // od tej klasy pochodzi dużo różnych klas
  78. {
  79. public:
  80. virtual ~RegisteredBase() {}
  81. virtual void WhoAmI()const=0; // tylko do demonstracji że to działa poprawnie
  82. };
  83.  
  84. // Typedef zeby korzystanie z fabryki bylo bardziej czytelne.
  85. typedef Factory<RegisteredBase> Register;
  86.  
  87. // Plik A.h
  88. class A:public RegisteredBase // jedna z tych "różnych klas
  89. {
  90. public:
  91. A() {}
  92. virtual void WhoAmI()const { std::cout<<"class A"<<std::endl; }
  93. };
  94.  
  95. // Rejestracja podobna jak u Ciebie.
  96. // Mozna to uprosisc uzywajac template aliases, ale na ideone to nie zadziala.
  97. Creator<RegisteredBase, A> CreatorA;
  98.  
  99. // Plik B.h
  100. class B:public RegisteredBase // jeszcze jedna z tych "różnych klas
  101. {
  102. public:
  103. B() {}
  104. virtual void WhoAmI()const { std::cout<<"class B"<<std::endl; }
  105. };
  106.  
  107. Creator<RegisteredBase, B> CreatorB;
  108.  
  109. // Plik C.h
  110. class C:public RegisteredBase // kolejna z tych "różnych klas
  111. {
  112. public:
  113. C() {}
  114. virtual void WhoAmI()const { std::cout<<"class C"<<std::endl; }
  115. };
  116.  
  117. Creator<RegisteredBase, C> CreatorC;
  118.  
  119. // main jest taki jak Twoj, tylko juz wczesniej zmienilem formatowanie.
  120. int main() {
  121. std::list<RegisteredBase *> obj;
  122.  
  123. for(Register::iterator it = Register::instance().begin();
  124. it != Register::instance().end();
  125. ++it) {
  126.  
  127. obj.push_back((*it)->create());
  128. }
  129.  
  130. for(std::list<RegisteredBase *>::iterator it = obj.begin();
  131. it != obj.end();
  132. ++it) {
  133.  
  134. (*it)->WhoAmI();
  135. delete *it;
  136. }
  137.  
  138. return 0;
  139. }
Success #stdin #stdout 0s 3020KB
stdin
Standard input is empty
stdout
class A
class B
class C