創(chuàng)建型設(shè)計(jì)模式-工廠模式

這篇博客講解工廠模式

概念

工廠模式是我們最常用的實(shí)例化對象模式了,是用工廠方法代替new操作的一種模式。


分類

工廠模式分類,簡單工廠模式,工廠方法模式,抽象工廠模式


簡單工廠模式

介紹

簡單工廠模式是屬于創(chuàng)建型模式,又叫做靜態(tài)工廠方法(Static Factory Method)模式,但不屬于23種GOF設(shè)計(jì)模式之一。簡單工廠模式是由一個工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例。簡單工廠模式是工廠模式家族中最簡單實(shí)用的模式,可以理解為是不同工廠模式的一個特殊實(shí)現(xiàn)。

延伸

試想一下,當(dāng)我們在codeing的時候,在A類里面只要NEW了一個B類的對象,那么A類就會從某種程度上依賴B類。如果在后期需求發(fā)生變化或者是維護(hù)的時候,需要修改B類的時候,我們就需要打開源代碼修改所有與這個類有關(guān)的類了,做過重構(gòu)的朋友都知道,這樣的事情雖然無法完全避免,但確實(shí)是一件讓人心碎的事情

場景

我發(fā)現(xiàn)大家寫這類博客都喜歡弄個場景,那我也弄個吧。假設(shè)你非常喜歡唱歌,是個歌手,每天晚上你都會回家唱一首歌曲,今天你唱《天天喜歡你》,明天喜歡唱《十年》,后天唱《明天就要嫁給你》,你每天唱那一首歌都是隨機(jī)的。

UML 圖


簡單工廠模式UML圖

簡單代碼

#import <Foundation/Foundation.h>

@protocol Song -(void)sing;

@end

#import "Song.h"

@interface SongA :?

NSObject

@end

#import "SongA.h"

@implementation SongA

-(void)sing{

? ? NSLog(@"sing 《天天喜歡你》");

}

@end

#import "Song.h"

@interface SongB : NSObject

@end

#import "SongB.h"

@implementation SongB

-(void)sing{

? ? NSLog(@"sing 《十年》");

}

@end

#import "Song.h"

@interface SongC : NSObject

@end

@implementation SongC

-(void)sing{

? ? NSLog(@"sing 《明天就要嫁給你》");

}

@end

#import "SongA.h"

#import "SongB.h"

#import "SongC.h"

#import "Song.h"

typedef enum {

SongAType,

SongBType,

SongCType}SongType;

@interface SongFactory : NSObject

-(id)getSongType:(SongType)songType;

@end

#import "SongFactory.h"

@implementation SongFactory

-(id)getSongType:(SongType)songType{

? ? if (songType==SongAType) {

? ? ? ? return [SongA? new];

? ? }else if (songType==SongBType){

? ? ? ? return [SongB new];

? ? }else if (songType == SongCType){

? ? ? ? return [SongC new];

? ? }else{

? ? ? ? return nil;

? ? }

? ? return nil;

}

@end

SongFactory * factory=[[SongFactory alloc]init]; id song = [factory getSongType:SongAType];

? ? [song sing];

? ? song = [factory getSongType:SongBType];

? ? [song sing];

? ? song = [factory getSongType:SongCType];

? ? [song sing];

測試結(jié)果很簡單

2018-04-02 17:31:55.153472+0800 創(chuàng)建型模式-工廠模式[31997:5155859] sing 《天天喜歡你》

2018-04-02 17:31:55.153638+0800 創(chuàng)建型模式-工廠模式[31997:5155859] sing 《十年》

2018-04-02 17:31:55.153745+0800 創(chuàng)建型模式-工廠模式[31997:5155859] sing 《明天就要嫁給你》

優(yōu)點(diǎn)

簡單工廠模式能夠根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個具體類的對象。明確區(qū)分了各自的職責(zé)和權(quán)力,有利于整個軟件體系結(jié)構(gòu)的優(yōu)化。

缺點(diǎn)

很明顯工廠類集中了所有實(shí)例的創(chuàng)建邏輯,容易違反GRASPR的高內(nèi)聚的責(zé)任分配原則


工廠方法模式

介紹

工廠方法模式Factory Method,又稱多態(tài)性工廠模式。在工廠方法模式中,核心的工廠類不再負(fù)責(zé)所有的產(chǎn)品的創(chuàng)建,而是將具體創(chuàng)建的工作交給子類去做。該核心類成為一個抽象工廠角色,僅負(fù)責(zé)給出具體工廠子類必須實(shí)現(xiàn)的接口,而不接觸哪一個產(chǎn)品類應(yīng)當(dāng)被實(shí)例化這種細(xì)節(jié)。

定義

工廠方法模式是簡單工廠模式的衍生,解決了許多簡單工廠模式的問題。首先完全實(shí)現(xiàn)‘開-閉 原則’,實(shí)現(xiàn)了可擴(kuò)展。其次更復(fù)雜的層次結(jié)構(gòu),可以應(yīng)用于產(chǎn)品結(jié)果復(fù)雜的場合。

延伸

在上面簡單工廠的引入中,我們將實(shí)例化具體對象的工作全部交給了專門負(fù)責(zé)創(chuàng)建對象的工廠類(場務(wù))中,這樣就可以在你需要唱歌的時候后創(chuàng)建對應(yīng)的歌曲(產(chǎn)品)類了。但是有時候唱歌有心情的,比如要唱一首新歌《青花瓷》,就必須要修改源碼,增加一個if else。工廠方法就是解決這個問題而產(chǎn)生的。

模擬場景

假設(shè)你今天想場《青花瓷》,明天想唱《霸王別姬》,每天想增加一手新歌,因此工廠模式的擴(kuò)展性增強(qiáng)很多

UML圖


工廠方法模式UML圖

其實(shí)我們看這個圖和簡單工廠的UML圖比較,就是將Factory 中根據(jù)type類型獲取歌曲變成了每一個工廠生產(chǎn)特定的歌曲。這樣每次增加一首歌曲,那么我們就增加一個factory就行了,不用在修改Factory類了

簡單代碼

歌曲abc 的代碼沒有任何變化

#import "Song.h"

@protocol MySongFactory<NSObject>

-(id)getSong;

@end

#import "MySongFactory.h"@interface SongFactoryA : NSObject<MySongFactory>

@end

#import "SongA.h"

@implementation SongFactoryA

-(id)getSong{

? ? return [SongA new];

}

@end

#import "MySongFactory.h"

@interface SongFactoryB : NSObject<MySongFactory>

@end

#import "SongFactoryB.h"

#import "SongB.h"

@implementation SongFactoryB

-(id<Song>)getSong{

? ? return [SongB new];

}

@end

#import "MySongFactory.h"

@interface SongFactoryC : NSObject<MySongFactory>

@end


#import "SongFactoryC.h"

#import "SongC.h"

@implementation SongFactoryC

-(id<Song>)getSong{

? ? return [SongC new];

}

@end

測試代碼

id<MySongFactory> factory=[SongFactoryA new];

id<Song> song = [factory getSong];

? ? [song sing];

? ? factory=[SongFactoryB new];

? ? song = [factory getSong];

? ? [song sing];

? ? factory=[SongFactoryC new];

? ? song = [factory getSong];

? ? [song sing];

測試結(jié)果

2018-04-02 18:21:39.573105+0800 創(chuàng)建型模式-工廠模式[44856:5211772] sing 《天天喜歡你》

2018-04-02 18:21:39.573325+0800 創(chuàng)建型模式-工廠模式[44856:5211772] sing 《十年》

2018-04-02 18:21:39.573447+0800 創(chuàng)建型模式-工廠模式[44856:5211772] sing 《明天就要嫁給你》

優(yōu)點(diǎn)

子類提供掛鉤?;悶楣S方法提供缺省實(shí)現(xiàn),子類可以重寫新的實(shí)現(xiàn),也可以繼承父類的實(shí)現(xiàn)。-- 加一層間接性,增加了靈活性

屏蔽產(chǎn)品類。產(chǎn)品類的實(shí)現(xiàn)如何變化,調(diào)用者都不需要關(guān)心,只需關(guān)心產(chǎn)品的接口,只要接口保持不變,系統(tǒng)中的上層模塊就不會發(fā)生變化。

典型的解耦框架。高層模塊只需要知道產(chǎn)品的抽象類,其他的實(shí)現(xiàn)類都不需要關(guān)心,符合迪米特法則,符合依賴倒置原則,符合里氏替換原則。

多態(tài)性:客戶代碼可以做到與特定應(yīng)用無關(guān),適用于任何實(shí)體類。

缺點(diǎn)

需要Creator和相應(yīng)的子類作為factory method的載體,如果應(yīng)用模型確實(shí)需要creator和子類存在,則很好;否則的話,需要增加一個類層次。(不過說這個缺點(diǎn)好像有點(diǎn)吹毛求疵了)

源代碼地址

借鑒博客


下一篇博客地址

創(chuàng)建性設(shè)計(jì)模式-抽象工廠模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容