强制一个通用的工厂来创建对象,而不允许将创建对象的代码散布于整个系统。如果程序中所有需要创建对象的代码都转到这个工厂执行,那么在增加新对象时所要做的全部工作就是只需修改工厂。
//: 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)来避免这种循环依赖。
//: 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);
} ///:~
现在,工厂方法模式作为virtual create()出现在它自己的ShapeFactory类中。这是一个私
有成员函数,意味着不能直接调用它,但可认被覆盖。Shape的子类必须创建各自的ShapeFactory
子类,并且覆盖成员函数create()以创建其自身类型的对象。这些工厂得私有的,只能被主
工厂方法模式访问。采用这种方法,所有客户代码都必须通过工厂方法模式创建对象。
抽象工厂模式看卢来和前面看到的工厂方法很相似,只是它使用若干工厂方法模式。每个工厂方法模式创建一个不同类型的对象。当创建一个工厂对象时,要决定将如何使用由那个工厂创建的所有对象。
//: 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 */ ///:~