這篇博客講解工廠模式
概念
工廠模式是我們最常用的實(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 圖

簡單代碼
#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圖

其實(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)吹毛求疵了)
源代碼地址
借鑒博客
下一篇博客地址