Greetings, I don't often create threads on this board, however, I'm looking for some constructive criticism on an idea i've been toying around with for the past couple of days. I've written a small semi-complete (compilable) program to demonstrate the concept (I haven't actually implemented a "Factory" as such yet, i'm still attempting to design the Dictionary portion)
I'm trying to find a work-around for the way a factory is normally setup, either with a pre-written set of case statements, if/else statements, or a lookup table - My idea is that the lookup table can be automatically generated by a static data member's initialisation call to a constructor (Which happens before main() begins) - and the constructor for the static members may fill up my dictionary for me. I wish to avoid writing/changing long, cumbersome lookup tables every time I add a class to my hierarchy.
fact_dict.hfact_dict.cppCode:#ifndef FACT_DICT_H #define FACT_DICT_H #include <string> #include <map> class EntityBase; typedef EntityBase* (*factory_t)(); class FactoryDictionary { typedef std::map< std::string, factory_t > edict_t; edict_t edict; FactoryDictionary() {}; FactoryDictionary(FactoryDictionary&) {}; public: factory_t lookup_from_string(std::string); static FactoryDictionary& get_dict(); bool insert(std::string, factory_t); }; class DictionaryLogger { public: DictionaryLogger(std::string, factory_t); }; #ifdef DICT_SETUP_CLASS #undef DICT_SETUP_CLASS #endif // DICT_SETUP_CLASS must be the first line in the class declaration #define DICT_SETUP_CLASS \ public: \ static EntityBase* fact_dict_create__(); \ private: \ static const DictionaryLogger fact_dict_record__ #ifdef DICT_REGISTER_CLASS #undef DICT_REGISTER_CLASS #endif // DICT_REGISTER_CLASS must go in the same file as the class implementation #define DICT_REGISTER_CLASS(classname) \ EntityBase* classname::fact_dict_create__() \ { \ return new classname; \ } \ const DictionaryLogger classname::fact_dict_record__ \ ( std::string( #classname ), &classname::fact_dict_create__ ) class EntityBase // All classes recorded in dictionary must be derived from here. { public: virtual std::string foo() =0; }; #endiftest.cppCode:#include <iostream> #include <string> #include <map> #include <utility> #include "fact_dict.h" // Wrapper for singleton dictionary object. FactoryDictionary& FactoryDictionary::get_dict() { static FactoryDictionary* fd = new FactoryDictionary(); return *fd; } bool FactoryDictionary::insert(std::string s, factory_t cf) { if (edict.find(s) == edict.end() ) { std::pair<std::string, factory_t> p(s, cf); edict.insert(p); return 1; } else { std::cout << "ERROR! " << s << " DUPLICATE FOUND. \n"; exit(EXIT_FAILURE); //TODO: Exception Handling } } factory_t FactoryDictionary::lookup_from_string(std::string s) { if (edict.find(s) == edict.end() ) { std::cout << s << " not found\n"; return NULL; } else return edict[s]; } DictionaryLogger::DictionaryLogger(std::string s, factory_t creator) { FactoryDictionary::get_dict().insert(s,creator); } // Pure virtual test function std::string EntityBase::foo() { return std::string ("This is the EntityBase \"foo\" \n"); }I've used constructs in this which are slightly "evil". I'm still undecided whether to keep the macros - on one hand I like the 'clean' look it gives to my entity classes, and the convenience, on the other hand, it obfuscates some details - although these are only details which should really be of no importance to any part of the program except the factory.Code:#include <iostream> #include <string> #include <map> #include <utility> #include "fact_dict.h" class EntityTest1 : public EntityBase { DICT_SETUP_CLASS; public: std::string foo(); }; DICT_REGISTER_CLASS(EntityTest1); std::string EntityTest1::foo() { return std::string("This is the EntityTest1 \"foo\" \n"); } int main() { FactoryDictionary& dictionary = FactoryDictionary::get_dict(); factory_t create_object = dictionary.lookup_from_string("EntityTest1"); EntityBase* eb = create_object(); std::cout << eb->foo(); delete eb; }
I've also neglected to add any kind of templating so far (although later I probably will), since this is a work-in-progress, I want to get the basic structure laid out before i begin messing with templates (Of course, ideally, it would be nice to have a completely generic factory & dictionary)
I've no idea whether there are already existing patterns or conventions in place for this kind of thing (I suspect they are, and i've been re-inventing the wheel), if there are, then I would certainly appreciate anyone pointing them out, so that I may slope-off and do it 'properly'
Otherwise, if anyone's got any criticisms/ideas/flames, i'd like to hear them, too
Thanks for your time
Bench



LinkBack URL
About LinkBacks




