/////////////////////////////////////////////////////////////// // MT1Q2b.cpp - Factory with Key // // // // Jim Fawcett, CSE687 - OOD Midterm, Spring 2013 // /////////////////////////////////////////////////////////////// /* * More realistic implementation of MT1Q2: * - uses copy constructor to create object with prototype's state * - uses IApplication interface so no need for client to use * dynamic_cast. Now the factory can do that because we have * one application interface. */ #include #include #include #include "../MTutility/MTutility.h" struct ICreatable { virtual ICreatable* create()=0; virtual ~ICreatable() {} void say() { std::cout << "\n " << typeid(*this).name() << " here"; } }; struct IApplication : public ICreatable { void nonVirtualSay() { std::cout << "\n " << typeid(*this).name() << ": non-virtual function call"; } virtual void virtualSay() = 0; }; class Factory { public: void registerPrototype(const std::string& key, IApplication* prototype); IApplication* createInstance(const std::string& key); ~Factory(); private: std::unordered_map map; }; void Factory::registerPrototype(const std::string& key, IApplication* ptr) { map[key] = ptr; } IApplication* Factory::createInstance(const std::string& key) { return dynamic_cast(map[key]->create()); } Factory::~Factory() { for(auto keyValuePair : map) delete keyValuePair.second; } class testBase : public IApplication { public: testBase(const std::string& phrase) : phrase_(phrase) { std::cout << "\n constructing testBase"; } testBase* create() { return new testBase(*this); } virtual void virtualSay() { std::cout << "\n testBase: virtual method call" << ", my phrase is: " << phrase_; } virtual ~testBase() { std::cout << "\n destroying testBase"; } private: std::string phrase_; }; class testDerived : public testBase { public: testDerived(const std::string& phrase) : testBase(""), phrase_(phrase) { std::cout << "\n constructing testDerived"; } testDerived* create() { return new testDerived(*this); } virtual void virtualSay() { std::cout << "\n testDerived: virtual method call" << ", my phrase is: " << phrase_; } virtual ~testDerived() { std::cout << "\n destroying testDerived"; } private: std::string phrase_; }; class other : public IApplication { public: other(int i) : myInt(i) { std::cout << "\n constructing other"; } other* create() { return new other(*this); } virtual void virtualSay() { std::cout << "\n other: virtual method call" << ", my int is: " << myInt; } ~other() { std::cout << "\n destroying other"; } private: int myInt; }; int main() { Title("MT1Q2 - Factory with key"); Factory factory; factory.registerPrototype("testBase", new testBase("base phrase")); factory.registerPrototype("testDerived", new testDerived("derived phrase")); factory.registerPrototype("other", new other(7)); IApplication* pTestBase = factory.createInstance("testBase"); pTestBase->say(); pTestBase->virtualSay(); pTestBase->nonVirtualSay(); delete pTestBase; // demonstrate that created objects can be used polymorphically IApplication* pTestDerived = factory.createInstance("testDerived"); pTestDerived->say(); pTestDerived->virtualSay(); pTestDerived->nonVirtualSay(); delete pTestDerived; // demonstrate IApplication* pOther = factory.createInstance("other"); pOther->say(); pOther->virtualSay(); pOther->nonVirtualSay(); delete pOther; std::cout << "\n\n"; }