设计模式(四)factory,Polymorphic factories,Abstract factories

    技术2022-06-29  83

    强制一个通用的工厂来创建对象,而不允许将创建对象的代码散布于整个系统。如果程序中所有需要创建对象的代码都转到这个工厂执行,那么在增加新对象时所要做的全部工作就是只需修改工厂。

      //: C10:ShapeFactory1.cpp #include <iostream> #include <stdexcept> #include <cstddef> #include <string> #include <vector> #include "../purge.h" using namespace std;   class Shape { public: virtual void draw() = 0; virtual void erase() = 0; virtual ~Shape() {} class BadShapeCreation : public logic_error { public: BadShapeCreation(string type) : logic_error("Cannot create type " + type) {} }; static Shape* factory(const string& type) throw(BadShapeCreation); };   class Circle : public Shape { Circle() {} // Private constructor friend class Shape; public: void draw() { cout << "Circle::draw" << endl; } void erase() { cout << "Circle::erase" << endl; } ~Circle() { cout << "Circle::~Circle" << endl; } };   class Square : public Shape { Square() {} friend class Shape; public: void draw() { cout << "Square::draw" << endl; } void erase() { cout << "Square::erase" << endl; } ~Square() { cout << "Square::~Square" << endl; } };   Shape* Shape::factory(const string& type) throw(Shape::BadShapeCreation) { if(type == "Circle") return new Circle; if(type == "Square") return new Square; throw BadShapeCreation(type); }   char* sl[] = { "Circle", "Square", "Square", "Circle", "Circle", "Circle", "Square" };   int main() { vector<Shape*> shapes; try { for(size_t i = 0; i < sizeof sl / sizeof sl[0]; i++) shapes.push_back(Shape::factory(sl[i])); } catch(Shape::BadShapeCreation e) { cout << e.what() << endl; purge(shapes); return EXIT_FAILURE; } for(size_t i = 0; i < shapes.size(); i++) { shapes[i]->draw(); shapes[i]->erase(); } purge(shapes); } ///:~   函数factory()允许以一个参数来决定创建何种类型的Shape。在这里,参数类型为string, 也可以是任何数据集。在添加新的Shape类型时,函数factory()是当前系统中惟一需要修改 的代码。(对象的初始化数据大概也可以由系统外获得,而不必像本例中那样来自硬编码数 组。) 这样的设计还有另外一个重要的含义--基类Shape现在必须了解每个派生类的细节--这 是面向对象设计试图避免的一个性质。对于结构框架或者任何类库来说都应该支持扩充,但 这样一来,系统很快就会变得笨拙,因为一旦新类型被加到这种层次结构中,基类就必须更 新。可以用下面的多态工厂(polymorphic factory)来避免这种循环依赖。
     
    Polymorphic factories
    //: C10:ShapeFactory2.cpp // Polymorphic Factory Methods. #include <iostream> #include <map> #include <string> #include <vector> #include <stdexcept> #include <cstddef> #include "../purge.h" using namespace std;   class Shape { public: virtual void draw() = 0; virtual void erase() = 0; virtual ~Shape() {} };   class ShapeFactory { virtual Shape* create() = 0; static map<string, ShapeFactory*> factories; public: virtual ~ShapeFactory() {} friend class ShapeFactoryInitializer; class BadShapeCreation : public logic_error { public: BadShapeCreation(string type) : logic_error("Cannot create type " + type) {} }; static Shape* createShape(const string& id) throw(BadShapeCreation) { if(factories.find(id) != factories.end()) return factories[id]->create(); else throw BadShapeCreation(id); } };   // Define the static object: map<string, ShapeFactory*> ShapeFactory::factories;   class Circle : public Shape { Circle() {} // Private constructor friend class ShapeFactoryInitializer; class Factory; friend class Factory; class Factory : public ShapeFactory { public: Shape* create() { return new Circle; } friend class ShapeFactoryInitializer; }; public: void draw() { cout << "Circle::draw" << endl; } void erase() { cout << "Circle::erase" << endl; } ~Circle() { cout << "Circle::~Circle" << endl; } };   class Square : public Shape { Square() {} friend class ShapeFactoryInitializer; class Factory; friend class Factory; class Factory : public ShapeFactory { public: Shape* create() { return new Square; } friend class ShapeFactoryInitializer; }; public: void draw() { cout << "Square::draw" << endl; } void erase() { cout << "Square::erase" << endl; } ~Square() { cout << "Square::~Square" << endl; } };   // Singleton to initialize the ShapeFactory: class ShapeFactoryInitializer { static ShapeFactoryInitializer si; ShapeFactoryInitializer() { ShapeFactory::factories["Circle"]= new Circle::Factory; ShapeFactory::factories["Square"]= new Square::Factory; } ~ShapeFactoryInitializer() { map<string, ShapeFactory*>::iterator it = ShapeFactory::factories.begin(); while(it != ShapeFactory::factories.end()) delete it++->second; } };   // Static member definition: ShapeFactoryInitializer ShapeFactoryInitializer::si;   char* sl[] = { "Circle", "Square", "Square", "Circle", "Circle", "Circle", "Square" };   int main() { vector<Shape*> shapes; try { for(size_t i = 0; i < sizeof sl / sizeof sl[0]; i++) shapes.push_back(ShapeFactory::createShape(sl[i])); } catch(ShapeFactory::BadShapeCreation e) { cout << e.what() << endl; return EXIT_FAILURE; } for(size_t i = 0; i < shapes.size(); i++) { shapes[i]->draw(); shapes[i]->erase(); } purge(shapes); } ///:~ .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   现在,工厂方法模式作为virtual create()出现在它自己的ShapeFactory类中。这是一个私 有成员函数,意味着不能直接调用它,但可认被覆盖。Shape的子类必须创建各自的ShapeFactory 子类,并且覆盖成员函数create()以创建其自身类型的对象。这些工厂得私有的,只能被主 工厂方法模式访问。采用这种方法,所有客户代码都必须通过工厂方法模式创建对象。 .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
    Abstract factories

    抽象工厂模式看卢来和前面看到的工厂方法很相似,只是它使用若干工厂方法模式。每个工厂方法模式创建一个不同类型的对象。当创建一个工厂对象时,要决定将如何使用由那个工厂创建的所有对象。

      //: C10:AbstractFactory.cpp // A gaming environment. #include <iostream> using namespace std;   class Obstacle { public: virtual void action() = 0; };   class Player { public: virtual void interactWith(Obstacle*) = 0; };   class Kitty: public Player { virtual void interactWith(Obstacle* ob) { cout << "Kitty has encountered a "; ob->action(); } };   class KungFuGuy: public Player { virtual void interactWith(Obstacle* ob) { cout << "KungFuGuy now battles against a "; ob->action(); } };   class Puzzle: public Obstacle { public: void action() { cout << "Puzzle" << endl; } };   class NastyWeapon: public Obstacle { public: void action() { cout << "NastyWeapon" << endl; } };   // The abstract factory: class GameElementFactory { public: virtual Player* makePlayer() = 0; virtual Obstacle* makeObstacle() = 0; };   // Concrete factories: class KittiesAndPuzzles : public GameElementFactory { public: virtual Player* makePlayer() { return new Kitty; } virtual Obstacle* makeObstacle() { return new Puzzle; } };   // Other Concrete factories: class KillAndDismember : public GameElementFactory { public: virtual Player* makePlayer() { return new KungFuGuy; } virtual Obstacle* makeObstacle() {return new NastyWeapon;} };   class GameEnvironment { GameElementFactory* gef;//环境 Player* p; //动作 Obstacle* ob; //角色 public: GameEnvironment(GameElementFactory* factory) : gef(factory), p(factory->makePlayer()), ob(factory->makeObstacle()) {} void play() { p->interactWith(ob); } ~GameEnvironment() { delete p; delete ob; delete gef; } };   int main() { GameEnvironment g1(new KittiesAndPuzzles), g2(new KillAndDismember); g1.play(); g2.play(); } /* Output: Kitty has encountered a Puzzle KungFuGuy now battles against a NastyWeapon */ ///:~   .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 在此环境中,Player对象与Obstrcle对象交互,但是Player和Obstacle类型依赖具体的游戏。可以选择特定的GameElementFactory来决定游戏的类型,然后GameEnvironment控制游戏的设置和进行。在本例中,游戏的设置和进行很简单,但是那些动作(初始条件和状态变化在很大程度上决定了游戏的结果。在这里,GameEnvironment不是设计成继承的,即使这样做可能是有意义的。

    最新回复(0)