幾乎在每個(gè)用面向?qū)ο笳Z言寫的應(yīng)用程序里都能看到工廠方法。工廠方法模式是抽象工廠模式的組成部分。各種具體工廠重載其抽象工廠父類中定義的工廠方法,并用這個(gè)重載的工廠方法創(chuàng)建自己的產(chǎn)品(對象)。
對象工廠與生產(chǎn)有形產(chǎn)品的真實(shí)工廠類似,例如,制鞋廠生產(chǎn)鞋,手機(jī)工廠生產(chǎn)手機(jī)。比方說,你讓工廠給你生產(chǎn)些產(chǎn)品,你給它們發(fā)送一個(gè)“生產(chǎn)產(chǎn)品”的消息。制鞋廠和手機(jī)工廠都按照相同的“生產(chǎn)產(chǎn)品”的協(xié)議,啟動(dòng)其生產(chǎn)線。過程結(jié)束后,每個(gè)廠家都返回所生產(chǎn)的特定類型的產(chǎn)品。我們把“生產(chǎn)”這個(gè)有魔力的詞稱作工廠方法,因?yàn)樗敲钌a(chǎn)者(工廠)得到想要的產(chǎn)品的方法。
生產(chǎn)者自身不必是抽象工廠,它可以是任何類。要點(diǎn)在于不是直接創(chuàng)建對象,而是使用類或?qū)ο蟮墓S方法創(chuàng)建具體產(chǎn)品,并以抽象類型返回。這樣做好在哪里?我們將在下面詳細(xì)討論。
1.何為工廠方法模式
工廠方法也稱為虛構(gòu)造器(virtual constructor)。它適用于這種情況:一個(gè)類無法預(yù)期需要生成哪個(gè)類的對象,想讓其子類來指定所生成的對象。
工廠方法模式的靜態(tài)類結(jié)構(gòu)如圖所示

抽象的Product(產(chǎn)品)定義了工廠方法創(chuàng)建的對象的接口。ConcreteProduct實(shí)現(xiàn)了Product接口。Creator定義了返回Product對象的工廠方法。它也可以為工廠方法定義一個(gè)默認(rèn)實(shí)現(xiàn),返回默認(rèn)ConcreteProduct對象。Creator的其他操作可以調(diào)用此工廠方法創(chuàng)建Product對象。ConcreateCreator是Creator的子類。它重載了工廠方法,以返回ConcreateProduct的實(shí)例。
工廠方法模式:定義創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個(gè)類。工廠方法使得一個(gè)類的實(shí)例化延遲到其子類。
2.何時(shí)使用工廠方法
在以下情形,你自然會想到使用工廠方法模式:
編譯時(shí)無法準(zhǔn)確預(yù)期要?jiǎng)?chuàng)建的對象的類;
類想讓其子類決定在運(yùn)行時(shí)創(chuàng)建什么;
類有若干輔助類為其子類,而你想將返回哪個(gè)子類這一消息局部化。
使用這一模式的最低限度是,工廠方法能給予類在變更返回哪一個(gè)對象這一點(diǎn)上更多的靈活性。使用這一結(jié)構(gòu)的一個(gè)常見例子是Cocoa Touch框架(或一般的Cocoa)中的NSNumber。盡管可以使用常見的alloc init兩步法創(chuàng)建NSNumber實(shí)例,但這沒什么用,除非使用預(yù)先定義的類工廠方法來創(chuàng)建有意義的實(shí)例。例如,[NSNumbeer numberWithBool:YES]消息會得到NSNumber的子類NSCFBoolean的一個(gè)實(shí)例,這個(gè)實(shí)例包含傳給類工廠方法的布爾值。工廠方法模式對框架設(shè)計(jì)者特別有用。
3.為何這是創(chuàng)建對象的安全方法
與直接創(chuàng)建新的具體對象對比,使用工廠方法創(chuàng)建對象可算作一種最佳做法。工廠方法模式讓客戶程序可以要求由工廠方法創(chuàng)建的對象擁有一組共同的行為。所以往類層次結(jié)構(gòu)中引入新的具體產(chǎn)品并不需要修改客戶端代碼,因?yàn)榉祷氐娜魏尉唧w對象的接口都跟客戶端一直在用的從前的接口相同。
代碼演示:
以下demo演示一個(gè)簡單工廠方法,通過一個(gè)工廠方法類創(chuàng)建不同的手機(jī)設(shè)備(蘋果手機(jī),安卓手機(jī),洛基亞手機(jī))
定義一個(gè)協(xié)議類,協(xié)議類的主要作用是篩選對象和規(guī)范接口
協(xié)議類:
《PhoneProtocol》

基本設(shè)備類:
《BaseDevice》
BaseDevice.h:

BaseDevice.m:

具體的設(shè)備類(蘋果手機(jī),安卓手機(jī),洛基亞手機(jī)),繼承于BaseDevice,并會實(shí)現(xiàn)PhoneProtocol協(xié)議
蘋果手機(jī)類《iPhoneDevice》:
iPhoneDevice.h:
注意,蘋果手機(jī)除了實(shí)現(xiàn)協(xié)議的方法外,還有一個(gè)自己的方法,這樣可以差異化創(chuàng)建產(chǎn)品

iPhoneDevice.m:

安卓手機(jī)類《AndroidDevice》:
注意,跟蘋果手機(jī)類一樣,安卓手機(jī)類也會有自己的一個(gè)方法,創(chuàng)建專屬于安卓手機(jī)的功能
AndroidDevice.h:

AndroidDevice.m:

洛基亞手機(jī)類《NokiaDevice》:
NokiaDevice.h:

NokiaDevice.m:

下面就是創(chuàng)建所有產(chǎn)品的工廠類《DeviceFactory》:
DeviceFactory.h:

DeviceFactory.m:

使用工廠方法創(chuàng)建具體的產(chǎn)品:
