ITK 中使用的其实是种称为 pluggable object factory 的设计模式,它可以在运行时进行动态替换,而且可以不修改已有代码的情况下添加处理新格式的图像文件类,等还有一些其它优点。它由两种模式组合而成:1.Abstract Factory 抽象工厂;2. Prototype 原型模式。还可能与单件模式(Singleton)组合。
简单的对象工厂可能如下所示:
1:
2: //Simple Factory
3: Circle
4: {
5: double radius;
6: }
7:
8: class Shape
9: {
10: public:
11: static Shape* newShape(istream&);
12: };
13: Shape* Shape::newShape(istream& params)
14: {
15: string className;
16: params >> className;
17: if (className == "Circle")
18: return new Circle(params);
19: else if (className == "Triangle")
20: return new Triangle(params);
21: else
22: //…
23: }
24:
Shape 是一个用来创建不同形状的对象工厂,Circle 是一种具体的形状。对象工厂 Shape 通过判断传入的参数,创建不同的对象实例。简单对象工厂的问题在于:1.基类 Shape 必须知道从它继承的每一个具体子类。2.当需要添加一种新的形状时,就得修改工厂方法 newShape()。这就违背了面向对象设计的“依赖倒置”原则(Dependency Inversion Principle),即高层模块不应该依赖于低层模块。同时还违背了“开-闭”原则(Opened-Closed),即 Open to extension,Closed to Modification。Pluggable Object Factory 模式可以解决这些问题。
Pluggable Object Factory,或者称为 PROTOTYPE–ABSTRACT FACTORY,可以将该模式归为创建型一类。
使用一个关联式容器如 map,关联容器中的每一个元素都是一个对象工厂,该对象工厂知道如何从一个抽象类层次结构中创建具体的子类对象实例。关联容器中的 key 则是用来从容器中查找合适的对象工厂。
Prototype Factory Compound Pattern:使用工厂方法,我们创建一个抽象类 ShapeMaker,它有一个静态的公有方法 newShape。一个具体的 CircleMaker 知道如何创建 circle 对象,它继承自 ShapeMaker。
1: //
2: class ShapeMaker
3: {
4: public:
5: static Shape* newShape(istream&);
6: protected:
7: typedef map<string,ShapeMaker*> MakerMap;
8: virtual Shape* makeShape(istream&) const&#61;0;
9: static MakerMap registry;
10: };
11: Shape* ShapeMaker::newShape(istream& is) {
12: string className;
13: is >> className;
14: ShapeMaker* maker &#61;
15: (*registry.find(className)).second;
16: return maker->makeShape(is);
17: }
18: //
19: class CircleMaker : public ShapeMaker
20: {
21: private:
22: Shape* makeShape(istream& params) const
23: {
24: return new Circle(params);
25: }
26: };
27:
同样&#xff0c;我们可以创建新的具体工厂类&#xff0c;如 TriangleMaker、RectangleMaker 等。每一个具体的工厂的实例都被保存于一个关联容器中。基类 ShapeMaker 通过一个 key 关联具体的工厂子类&#xff0c;如上面代码所示这里的 key 使用的是类名 className。 newShape(className) 通过在关联容器中查找对应于 className 的具体的对象工厂来创建具体的对象实例。这样&#xff0c;我们便可以不修改工厂方法而添加新的对象工厂。
Registering Factories Using Prototype&#xff1a;Prototype 原型模式提供了在关联容器中动态注册对象工厂的方法。每一个具体的对象工厂都维护一个自身的静态对象实例变量&#xff0c;该静态对象实例的唯一目的就是在基类的静态关联容器中注册自己。
1:
2: //
3: class CircleMaker : public ShapeMaker
4: {
5: private:
6: CircleMaker() : ShapeMaker("Circle") {}
7: static const CircleMaker registerThis;
8: };
9: //其中&#xff1a;
10: ShapeMaker::ShapeMaker(string className)
11: {
12: //在基类的静态关联容器中注册自己
13: registry.insert( make_pair(className, this) );
14: }
15: //使用&#xff1a;
16: fstream params("shapes.txt");
17: Shape* shape &#61; ShapeMaker::newShape(params);
18:
Plugging in with Prototype Factory&#xff1a;Factory Method 工厂方法与 Prototype 原型模式结合&#xff0c;允许工程扩展 ShapeMaker可以创建对象的 Shape 类型。ShapeMaker 类以及与其协作的其它类表示了 Prototype Factory 模式。Factory Method 工厂方法提供创建对象实例的方法&#xff0c;Prototype 原型模式提供在运行时动态注册对象工厂的方法。
1.GENERIC FACTORIES 泛化工厂&#xff1a;从上面的 Prototype Factory 模式可以看出&#xff0c;算法与数据类型是相互独立的&#xff0c;所以我们使用模板实现 Prototype Factory 组合模式&#xff1a;
1:
2: //Generic 工厂
3: template<class Object>
4: class Maker
5: {
6: public:
7: virtual ~Maker();
8: static Object* newObject(istream&);
9: protected:
10: Maker(const string& className);
11: virtual Object* makeObject(istream&) const&#61;0;
12: private:
13: typedef Maker