Created
December 14, 2023 09:49
-
-
Save potados99/6eb45216e384cf6ce83e93c90f8fe5cb to your computer and use it in GitHub Desktop.
Self registering factory pattern, modified
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Original source code from: https://www.nirfriedman.com/2018/04/29/unforgettable-factory/ | |
*/ | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
template<class Base> | |
class Factory { | |
public: | |
friend Base; | |
static Base *find(const std::string &s) { | |
for (Base *instance: Factory::data()) { | |
if (instance->match(s)) { | |
return instance; | |
} | |
} | |
throw 9; | |
} | |
template<class T> | |
struct Registrar : Base { | |
friend T; | |
static bool registered; | |
static bool registerT() { | |
Factory::data().push_back(new T()); | |
return true; | |
} | |
private: | |
Registrar() : Base(Key{}) { (void) registered; } | |
}; | |
private: | |
class Key { | |
Key() {}; | |
template<class T> friend | |
struct Registrar; | |
}; | |
static std::vector<Base *> &data() { | |
static std::vector<Base *> instances; | |
return instances; | |
} | |
}; | |
template<class Base> | |
template<class T> | |
bool Factory<Base>::Registrar<T>::registered = Factory<Base>::Registrar<T>::registerT(); | |
struct Animal : Factory<Animal> { | |
Animal(Key) {} | |
virtual void makeNoise() = 0; | |
virtual bool match(const std::string &s) = 0; | |
}; | |
class Dog : public Animal::Registrar<Dog> { | |
public: | |
Dog() {} | |
bool match(const std::string &s) { return s.compare("Dog") == 0; } | |
void makeNoise() { std::cerr << "Dog: " << 123 << "\n"; } | |
}; | |
class Cat : public Animal::Registrar<Cat> { | |
public: | |
Cat() {} | |
bool match(const std::string &s) { return s.compare("Cat") == 0; } | |
void makeNoise() { std::cerr << "Cat: " << 123 << "\n"; } | |
}; | |
int main() { | |
auto x = Animal::find("Cat"); | |
auto y = Animal::find("Dog"); | |
std::cout << "Hello, World!" << std::endl; | |
x->makeNoise(); | |
y->makeNoise(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment