// Purpose. Abstract Factory #include // // Discussion. Trying to maintain class Widget { public: // portability across multiple "plat- virtual void draw() = 0; // forms" routinely requires lots of }; // preprocessor "case" stmts. The // Factory pattern suggests defining class MotifBtn : public Widget { // a creation services interface in a public: // Factory base class, and implement- void draw() { cout << "MotifBtn" // ing each "platform" in a separate << endl; } // Factory derived class. }; #include class WindowsBtn : public Widget { public: class Widget { public: void draw() { cout << "WindowsBtn" virtual void draw() = 0; << endl; } }; }; class MotifBtn : public Widget { class Factory { public: public: virtual Widget* createBtn() = 0; void draw() { cout << "MotifBtn" }; << endl; } }; class MotifFactory : public Factory { public: class WindowsBtn : public Widget { Widget* createBtn() { public: return new MotifBtn; } void draw() { cout << "WindowsBtn" }; << endl; } }; class WindowsFactory : public Factory { public: void doThisWindow() { Widget* createBtn() { // create window, attach btn return new WindowsBtn; } #ifdef MOTIF }; Widget* w = new MotifBtn; #else // WINDOWS Factory* factory; Widget* w = new WindowsBtn; #endif void doThisWindow() { w->draw(); } // create window, attach btn Widget* w = factory->createBtn(); void doThatWindow() { w->draw(); } // create window, attach btn #ifdef MOTIF void doThatWindow() { Widget* w = new MotifBtn; // create window, attach btn #else // WINDOWS Widget* w = factory->createBtn(); Widget* w = new WindowsBtn; w->draw(); } #endif w->draw(); } void main( void ) { void main( void ) #ifdef MOTIF { factory = new MotifFactory; // create window, attach btn #else // WINDOWS #ifdef MOTIF factory = new WindowsFactory; Widget* w = new MotifBtn; #endif #else // WINDOWS Widget* w = new WindowsBtn; // create window, attach btn #endif Widget* w = factory->createBtn(); w->draw(); w->draw(); doThisWindow(); doThisWindow(); doThatWindow(); doThatWindow(); } } // WindowsBtn // MotifBtn // WindowsBtn // MotifBtn // WindowsBtn // MotifBtn // Purpose. Abstract Factory design pattern demo. // // Discussion. "Think of constructors as factories that churn out objects". // Here we are allocating the constructor responsibility to a factory object, // and then using inheritance and virtual member functions to provide a // "virtual constructor" capability. So there are two dimensions of // decoupling occurring. The client uses the factory object instead of "new" // to request instances; and, the client "hard-wires" the family, or class, of // that factory only once, and throughout the remainder of the application // only relies on the abstract base class. #include class Shape { public: Shape() { id_ = total_++; } virtual void draw() = 0; protected: int id_; static int total_; }; int Shape::total_ = 0; class Circle : public Shape { public: void draw() { cout << "circle " << id_ << ": draw" << endl; } }; class Square : public Shape { public: void draw() { cout << "square " << id_ << ": draw" << endl; } }; class Ellipse : public Shape { public: void draw() { cout << "ellipse " << id_ << ": draw" << endl; } }; class Rectangle : public Shape { public: void draw() { cout << "rectangle " << id_ << ": draw" << endl; } }; class Factory { public: virtual Shape* createCurvedInstance() = 0; virtual Shape* createStraightInstance() = 0; }; class SimpleShapeFactory : public Factory { public: Shape* createCurvedInstance() { return new Circle; } Shape* createStraightInstance() { return new Square; } }; class RobustShapeFactory : public Factory { public: Shape* createCurvedInstance() { return new Ellipse; } Shape* createStraightInstance() { return new Rectangle; } }; void main() { #ifdef SIMPLE Factory* factory = new SimpleShapeFactory; #elif ROBUST Factory* factory = new RobustShapeFactory; #endif Shape* shapes[3]; shapes[0] = factory->createCurvedInstance(); // shapes[0] = new Ellipse; shapes[1] = factory->createStraightInstance(); // shapes[1] = new Rectangle; shapes[2] = factory->createCurvedInstance(); // shapes[2] = new Ellipse; for (int i=0; i < 3; i++) shapes[i]->draw(); } // ellipse 0: draw // rectangle 1: draw // ellipse 2: draw