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=0;
9: static MakerMap registry;
10: };
11: Shape* ShapeMaker::newShape(istream& is) {
12: string className;
13: is >> className;
14: ShapeMaker* maker =
15: (*registry.find(className)).second;
16: return maker->makeShape(is);
17: }
18: //
19: class CircleMaker : public ShapeMaker
20: {
21: private:
23: {
24: return new Circle(params);
25: }
26: };
27:
同樣,我們可以建立新的具體工廠類,如 TriangleMaker、RectangleMaker 等。每一個具體的工廠的執行個體都被儲存于一個關聯容器中。基類 ShapeMaker 通過一個 key 關聯具體的工廠子類,如上面代碼所示這裡的 key 使用的是類名 className。 newShape(className) 通過在關聯容器中查找對應于 className 的具體的對象工廠來建立具體的對象執行個體。這樣,我們便可以不修改工廠方法而添加新的對象工廠。 Registering Factories Using Prototype:Prototype 原型模式提供了在關聯容器中動态注冊對象工廠的方法。每一個具體的對象工廠都維護一個自身的靜态對象執行個體變量,該靜态對象執行個體的唯一目的就是在基類的靜态關聯容器中注冊自己。
1:
2: //
3: class CircleMaker : public ShapeMaker
4: {
5: private:
6: CircleMaker() : ShapeMaker("Circle") {}
7: static const CircleMaker registerThis;
8: };
9: //其中:
10: ShapeMaker::ShapeMaker(string className)
11: {
12: //在基類的靜态關聯容器中注冊自己
13: registry.insert( make_pair(className, this) );
14: }
15: //使用:
16: fstream params("shapes.txt");
17: Shape* shape = ShapeMaker::newShape(params);
18:
Plugging in with Prototype Factory:Factory Method 工廠方法與 Prototype 原型模式結合,允許工程擴充 ShapeMaker可以建立對象的 Shape 類型。ShapeMaker 類以及與其協作的其它類表示了 Prototype Factory 模式。Factory Method 工廠方法提供建立對象執行個體的方法,Prototype 原型模式提供在運作時動态注冊對象工廠的方法。
1.GENERIC FACTORIES泛化工廠:從上面的 Prototype Factory 模式可以看出,算法與資料類型是互相獨立的,是以我們使用模闆實作 Prototype Factory 組合模式:
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=0;
12: private:
13: typedef Maker