//: C09:ShapeFactory2.cpp // From Thinking in C++, 2nd Edition // Available at http://www.BruceEckel.com // (c) Bruce Eckel 2000 // Copyright notice in Copyright.txt // Polymorphic factory methods #include "../purge.h" #include #include #include #include #include using namespace std; class Shape { public: virtual void draw() = 0; virtual void erase() = 0; virtual ~Shape() {} }; class ShapeFactory { virtual Shape* create() = 0; static map factories; public: virtual ~ShapeFactory() {} friend class ShapeFactoryInizializer; class BadShapeCreation : public exception { string reason; public: BadShapeCreation(string type) { reason = "Cannot create type " + type; } const char *what() const { return reason.c_str(); } }; static Shape* createShape(string id) throw(BadShapeCreation){ if(factories.find(id) != factories.end()) return factories[id]->create(); else throw BadShapeCreation(id); } }; // Define the static object: map ShapeFactory::factories; class Circle : public Shape { Circle() {} // Private constructor public: void draw() { cout << "Circle::draw\n"; } void erase() { cout << "Circle::erase\n"; } ~Circle() { cout << "Circle::~Circle\n"; } class Factory; friend class Factory; class Factory : public ShapeFactory { public: Shape* create() { return new Circle; } }; }; class Square : public Shape { Square() {} public: void draw() { cout << "Square::draw\n"; } void erase() { cout << "Square::erase\n"; } ~Square() { cout << "Square::~Square\n"; } class Factory; friend class Factory; class Factory : public ShapeFactory { public: Shape* create() { return new Square; } }; }; // Singleton to initialize the ShapeFactory: class ShapeFactoryInizializer { static ShapeFactoryInizializer si; ShapeFactoryInizializer() { ShapeFactory::factories["Circle"] = new Circle::Factory; ShapeFactory::factories["Square"] = new Square::Factory; } }; // Static member definition: ShapeFactoryInizializer ShapeFactoryInizializer::si; char* shlist[] = { "Circle", "Square", "Square", "Circle", "Circle", "Circle", "Square", "" }; int main() { vector shapes; try { for(char** cp = shlist; **cp; cp++) shapes.push_back( ShapeFactory::createShape(*cp)); } catch(ShapeFactory::BadShapeCreation e) { cout << e.what() << endl; return 1; } for(int i = 0; i < shapes.size(); i++) { shapes[i]->draw(); shapes[i]->erase(); } purge(shapes); } ///:~