設(shè)計模式之FactoryMethod模式
FactoryMethod模式屬于23種設(shè)計模式中的創(chuàng)建型模式,解決的是如何“new”的問題。引例:
還是先從簡單的例子入手FactoryMethod模式吧,現(xiàn)在需要一個汽車測試的環(huán)境來對汽車進(jìn)行測試,我們很容易會這樣設(shè)計

/**///////////////////////////////////////////////2
//汽車類3
class Car4


{5
public:6

void Startup()
{}7

void Run()
{}8

void Turn()
{}9

void Stop()
{}10
};11

12

/**///////////////////////////////////////////////13
//汽車測試環(huán)境14
class CarTestFramework15


{16
public:17
void DoTest()18

{19
Car* car = new Car();20
car->Startup();21
car->Run();22
car->Turn();23
car->Stop();24
}25
};非常簡單的設(shè)計,但是存在問題,如果我們要對紅旗車,東風(fēng)車進(jìn)行測試,那么怎么辦?
有了之前那些模式的經(jīng)驗,再回想下面向?qū)ο蟮奶匦浴!!?br>“多態(tài)”!將Car設(shè)計成為一個抽象類,DoTest里全部使用抽象類的指針來操作,那不就可以應(yīng)對不同類型的汽車了嗎?
于是有了以下的代碼:(注意DoTest的參數(shù),這樣使用才可以讓用戶指定車輛的類型)

/**///////////////////////////////////////////////
//抽象汽車類
class AbstractCar

{
public:
virtual void Startup() = 0;
virtual void Run() = 0;
virtual void Turn() = 0;
virtual void Stop() =0;
};

/**///////////////////////////////////////////////
//具體汽車類——紅旗車
class HongqiCar : public AbstractCar

{
public:
//具體實現(xiàn)抽象汽車類的四個方法
.
};

/**///////////////////////////////////////////////
//汽車測試環(huán)境
class CarTestFramework

{
public:
void DoTest(AbstractCar* car)
{
car->Startup();
car->Run();
car->Turn();
car->Stop();
}
};到此為止的設(shè)計其實還是不錯的,能夠應(yīng)對不同類型的汽車變化,如果增加了新的汽車類型也完全不用修改現(xiàn)有代碼,只需要增加代碼就可以了
但如果測試車輛不止一輛怎么辦?以上設(shè)計的缺陷就在于DoTest的參數(shù),參數(shù)的個數(shù)對應(yīng)于測試車輛的數(shù)量,測試數(shù)量不確定是很正常的事情。
再想想面向?qū)ο笥惺裁刺匦浴!!?#8220;封裝”!用一個類專門用來封裝汽車的創(chuàng)建就搞定這個問題了嘛!這個類起個特別的名字就是“工廠類”。
動機:
軟件系統(tǒng)中,我們經(jīng)常面對“某個對象”的創(chuàng)建工作;由于需求的變化,這個對象經(jīng)常面臨劇烈的變化,但他有相對穩(wěn)定的接口。
為了抵抗這種變化,提出“封裝變化點”的思想,采用“封裝”機制將其“變化部分”隔離出來,從而保證“其他依賴該對象的對象”不隨需求變化而變化。
意圖:
定義一個用于創(chuàng)建對象的接口,讓子類決定實例化哪個類。Factory Method使得一個類的實例化延遲到子類。(GoF23)
設(shè)計思路:
還是先看看UML圖
如果只看左邊的Product和ConcreteProduct部分,那么這就是我們的第2種設(shè)計方案。
FatoryMethod在Product和ConcreteProduct的基礎(chǔ)上加上了Creator和ConcreteCreator,分別就是Factory和ConcreteFactory。Factory有個非常重要的函數(shù)CreateProduct()(就是圖中的AnOperation),它將對象的創(chuàng)建工作封裝了起來。
總結(jié):
1.OO的“多態(tài)”。大部分的設(shè)計模式都會體現(xiàn)出OO的這個原則,他的作用就是“推遲實現(xiàn)”,將一個類的實例化推遲到子類,從而解決不同類型對象的創(chuàng)建問題。
2.OO的“封裝”。工廠方法另一個重要思想,工廠類把創(chuàng)建工作封裝起來,這樣用戶就可以多次使用,解決了同時創(chuàng)建多個對象的問題。
3.工廠方法和抽象工廠的區(qū)別:其實抽象工廠模式可以看作工廠模式的一個特例。工廠模式在工廠類中只創(chuàng)建一種類型的對象,如果在工廠類中擁有創(chuàng)建多種類型的對象的方法(比如創(chuàng)建引擎,創(chuàng)建車門,創(chuàng)建車燈。。。)那其實不就是之前討論的抽象工廠模式嘛?
4.當(dāng)我們創(chuàng)建一系列有繼承關(guān)系的類時都可以考慮使用工廠方法。回想之前項目中使用的Ogre,工廠方法使用非常廣泛,幾乎所有對象都不是new出來的,Ogre提供了許許多多的CreateXX方法。
自己做的示例代碼,僅供參考:
AbstractFactory.h
#pragma once2
#include "AbstractCar.h"3

4
class AbstractCarFactory5


{6
public:7
virtual AbstractCar* CreateCar() = 0;8
};
#pragma once2

3
class AbstractCar4


{5
public:6
virtual void Startup() = 0;7
virtual void Run() = 0;8
virtual void Turn() = 0;9
virtual void Stop() = 0;10
};11

#pragma once2
#include "AbstractCarFactory.h"3
#include "HongqiCar.h"4

5
class HongqiCarFactory :public AbstractCarFactory6


{7
public:8
virtual AbstractCar* CreateCar()9

{10
return new HongqiCar();11
}12
};13

#pragma once2
#include "AbstractCar.h"3
#include <iostream>4
using namespace std;5

6
class HongqiCar : public AbstractCar7


{8
public:9
virtual void Startup()10

{11
cout<<"HongqiCar : Startup()"<<endl;12
}13
virtual void Run()14

{15
cout<<"HongqiCar : Run()"<<endl;16
}17
virtual void Turn()18

{19
cout<<"HongqiCar : Turn()"<<endl;20
}21
virtual void Stop()22

{23
cout<<"HongqiCar : Stop()"<<endl;24
}25
};26


/**///////////////////////////////////////////////////////////////////////////2
// FactoryMethodTest for Factory Method Test3

/**///////////////////////////////////////////////////////////////////////////4

5
#include "stdafx.h"6
#include "AbstractCar.h"7
#include "AbstractCarFactory.h"8
#include "HongqiCar.h"9
#include "HongqiCarFactory.h"10
#include <iostream>11
using namespace std;12

13

14
class CarTestFramework15


{16
public:17
void DoTest(AbstractCarFactory* carFactory)18

{19
AbstractCar* car1 = carFactory->CreateCar();20
cout<<"//////////////////////////////////////////////\n//Car1 Test\n//////////////////////////////////////////////"<<endl;21
car1->Startup();22
car1->Run();23
car1->Turn();24
car1->Stop();25

26
AbstractCar* car2 = carFactory->CreateCar();27
cout<<"\n//////////////////////////////////////////////\n//Car2 Test\n//////////////////////////////////////////////"<<endl;28
car2->Startup();29
car2->Run();30
car2->Turn();31
car2->Stop();32
}33
};34

35

36
int _tmain(int argc, _TCHAR* argv[])37


{38
CarTestFramework* carTestFramework = new CarTestFramework();39
cout<<"Test the HongqiCar"<<endl;40
carTestFramework->DoTest(new HongqiCarFactory());41

42
return 0;43
}44

45

posted on 2009-04-08 20:58 Alex@VCC 閱讀(1777) 評論(7) 編輯 收藏 引用 所屬分類: 設(shè)計模式

