在上篇中,静态成员函数 static Shape* factory(const string& type) 迫使所有创建对象的操作都集中在一个地方,
因此这个地方就是唯一需要修改代码的地方。这是一个合理的决解方法,因为它完美的封装了对象的创建过程。
但是工厂方法模式——可以使不同类型的的工厂派生自基本类型的工厂。工厂方法事实上就是多态工厂模式的一个特例。
所以下面例子是——工厂方法模式做为一个单独的类中的虚函数出现。
#include <stdexcept>
#include <cstddef>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
template<class Seq> void purge(Seq& c)
{
typename Seq::iterator i;
for(i = c.begin(); i != c.end(); ++i)
{
delete *i;
*i = 0;
}
}
// Iterator version:
template<class InpIt> void purge(InpIt begin, InpIt end)
{
while(begin != end)
{
delete *begin;
*begin = 0;
++begin;
}
}
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 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 -1;
}
for(size_t i = 0; i < shapes.size(); i++)
{
shapes[i]->draw();
shapes[i]->erase();
}
purge(shapes);
}
工厂方法模式作为virtual create() 出现在它自己的 ShapeFactory 类中,这是一个私有的成员函数。意味着不能直接调用它,但是可以被覆盖。
Shape 的子类必须创建各自的 ShapeFactory子类,并且覆盖成员函数 create()以创建其自身类型的对象。
这些工厂是私有的,只能被工厂方法模式访问。采用这种方法的所有客户代码都必须通过工厂方法模式创建对象。
Shape对象的实际创建是通过调用ShapeFactory::createShape() 完成对的,这是一个静态成员函数,
使用ShapeFactory 中的map 根据传递给它的标识符找到相应的工厂对象。
工厂直接创建Shape 对象,但是可以设想一个更为复杂的问题:在某个地方返回一个合适的工厂对象。然后该工厂对象被调用者用于以更复杂的方法创建一个对象。
然而,似乎在大多数情况下不需要这么复杂地使用多态工厂方法模式。
注意,ShapeFactory 必须通过装载它的map 与工厂对象进行初始化,这些操作发生在单例ShapeFactoryInitializer, 以便将工厂的一个实例插入到map中。
这些额外的复杂的操作再次暗示,如果不需要创建独立的工厂对象,应该尽可能使用静态(static)工厂方法模式