該文章屬于劉小壯原創(chuàng),轉(zhuǎn)載請注明:劉小壯
這是工廠模式三部曲中的最后一篇了躲撰,在這篇文章中將會講述抽象工廠模式枫耳,抽象工廠模式正如其名字一樣,非常抽象寓落。但是抽象工廠模式的功能卻十分強大炊豪,對抽象工廠的利用也非常好。
這篇文章中會像本系列第一篇一樣鸯檬,給出普通實現(xiàn)方式和使用了反射機制的實現(xiàn)兩種代碼决侈,并且會說明這兩種實現(xiàn)方式的區(qū)別。并且在文章的最后喧务,會將這三種模式放在一起赖歌,對這三種工廠模式進行總結(jié)。
本人理解可能不夠深刻功茴,這一系列文章中存在的問題庐冯,歡迎大家提出,謝謝坎穿!??
什么是抽象工廠模式
簡單了解一下
按照慣例展父,我們先了解一下什么是抽象工廠模式。抽象工廠模式和工廠方法模式很相似赁酝,但是抽象工廠模式將抽象發(fā)揮的更加極致犯祠,是三種工廠模式中最抽象的一種設(shè)計模式。抽象工廠模式酌呆,也叫做Kit模式衡载,提供了創(chuàng)建一系列相關(guān)抽象子類的接口,而無需指定它們具體的類型隙袁。
抽象工廠模式中定義了抽象工廠類痰娱,抽象工廠類中定義了每個系列的抽象子類創(chuàng)建所需的方法,這些方法對應(yīng)著不同類型的抽象子類實例化過程菩收。每個工廠子類都對應(yīng)著一個系列梨睁,工廠子類通過重寫這些方法來實例化當前系列的抽象子類。
工廠方法模式中抽象子類都是基于同一個抽象類的娜饵,是同一個類型的抽象子類坡贺,例如加、減箱舞、乘遍坟、除都屬于運算類型。而抽象工廠模式可能會有多個類型的抽象類晴股,抽象子類分別繼承自對應(yīng)類型的抽象類愿伴,相同類型的抽象子類都是屬于不同系列的。
抽象工廠模式包含四部分:
- 抽象工廠類:定義創(chuàng)建抽象子類的具體行為电湘,根據(jù)系列中不同類型的抽象子類可能會有多種行為隔节。
- 工廠子類:繼承自抽象工廠類鹅经,根據(jù)當前抽象子類對應(yīng)的系列,重寫父類定義的對應(yīng)行為怎诫。對應(yīng)的抽象子類系列不同瘾晃,行為的實現(xiàn)方式也不同。
- 抽象類:定義當前類型抽象子類的操作刽虹,子類繼承父類完成具體的操作酗捌。在抽象工廠模式中呢诬,可能會有多種抽象類的定義涌哲。
- 抽象子類:根據(jù)當前類型繼承自對應(yīng)的抽象類,并根據(jù)系列的不同重寫抽象類定義的實現(xiàn)尚镰。
我打算先講一個例子
我們上面講了系列的概念阀圾,這里將會用一個例子來理解系列和抽象類的關(guān)系。假設(shè)現(xiàn)在需要用Sqlite
和CoreData
兩種不同的方式進行本地持久化狗唉,持久化的內(nèi)容都是用戶信息初烘、搜索信息、設(shè)置信息三部分分俯。
就拿Sqlite
持久化方式來說肾筐,Sqlite
就是使用Sqlite
數(shù)據(jù)庫持久化方式的系列,下面對應(yīng)著用戶信息缸剪、搜索信息吗铐、設(shè)置信息三個類型,每個類型就是一個抽象類杏节。除了Sqlite
這種持久化方式外唬渗,還有CoreData
這種持久化方式,這是兩個不同的持久化方式奋渔,所以屬于兩個不同的系列镊逝。
Sqlite
和CoreData
都代表著不同的系列,其下面都分別對應(yīng)著用戶信息嫉鲸、搜索信息撑蒜、設(shè)置信息三個類型的層級,在這種層級關(guān)系中玄渗,Sqlite
的用戶信息抽象子類對應(yīng)著CoreData
的用戶信息抽象子類座菠,這兩個抽象子類都屬于同一個類型,繼承自同一個抽象類捻爷,分別被不同系列的工廠子類創(chuàng)建辈灼。在抽象設(shè)計模式中,不同系列相同類型的抽象子類都是一一對應(yīng)的也榄。
Sqlite
和CoreData
屬于不同的系列巡莹,所以是兩個不同的工廠子類司志,這兩個工廠子類具有相同的行為,就是用戶信息降宅、搜索信息骂远、設(shè)置信息三部分的數(shù)據(jù)持久化,這就是三種不同的持久化類型腰根,也就是我們上面說的類型激才。這三個行為定義在抽象工廠類中,抽象工廠類中定義每個系列的抽象子類創(chuàng)建方法额嘿,Sqlite
和CoreData
繼承自抽象工廠類瘸恼,并分別實現(xiàn)繼承過來的抽象子類創(chuàng)建方法。
通過上面的例子册养,我們可以清晰的理解工廠類东帅、抽象類、系列三者之間的關(guān)系球拦,理解這三者的關(guān)系可以有助于我們更好的理解抽象設(shè)計模式靠闭。
和工廠方法模式有什么不同?
在工廠方法模式中坎炼,工廠子類負責(zé)抽象子類的實例化愧膀,每個工廠子類對應(yīng)著一個抽象子類,且具有唯一性谣光。而在抽象工廠模式中檩淋,一個工廠子類代表一個系列,工廠子類根據(jù)當前系列對不同類型的抽象子類進行創(chuàng)建抢肛。工廠方法模式中工廠子類對應(yīng)的是一個類型的抽象子類狼钮,抽象工廠模式對應(yīng)的是一個系列的抽象子類。
工廠方法模式一個工廠子類對應(yīng)一個抽象子類的設(shè)計捡絮,會有很大的浪費熬芜,產(chǎn)生了過多的類。而抽象工廠模式更好的利用了工廠子類福稳,使每個工廠子類對應(yīng)著一個系列的抽象子類涎拉,這種設(shè)計非常適用于兩個具有相同結(jié)構(gòu)關(guān)系,但是分屬于不同系列的系列之間的切換的圆。
總之就是鼓拧,工廠方法模式是針對單個類型的抽象類,而抽象工廠模式是針對具有相同結(jié)構(gòu)的一系列類型的抽象類越妈。
業(yè)務(wù)場景
在上面講到了數(shù)據(jù)持久化的例子季俩,我們的業(yè)務(wù)場景也根據(jù)上面的例子提出。
在iOS
中比較常用的數(shù)據(jù)持久化方案梅掠,應(yīng)該就包括Sqlite
和CoreData
了酌住,可能Sqlite
的靈活性使其更加受歡迎店归。業(yè)務(wù)就是需要用Sqlite
和CoreData
兩種不同的方式進行本地持久化,持久化的內(nèi)容是用戶信息酪我、搜索信息消痛、設(shè)置信息三部分。
通過抽象工廠模式實現(xiàn)上面的需求都哭,可以很方便的進行本地持久化方案的切換秩伞,下面的例子中將會演示一行代碼切換數(shù)據(jù)持久化方案的例子。
UML類圖
我們根據(jù)上面的業(yè)務(wù)場景畫了一個UML類圖欺矫,下面類圖中為了讓大家看得更清晰纱新,所以用不同顏色的線區(qū)分開了對應(yīng)的類和功能。
下面的黑色箭頭是抽象子類和抽象類的繼承關(guān)系汇陆;紅色是用戶工廠子類對應(yīng)的抽象子類怒炸;黃色是搜索工廠子類對應(yīng)的抽象子類带饱;綠色是設(shè)置工廠子類對應(yīng)的抽象子類毡代。
在這個UML類圖中,我們可以清晰的看出勺疼,之前工廠方法模式的工廠子類對應(yīng)的是單一類型的抽象子類教寂,上面抽象工廠模式的工廠子類對應(yīng)的是同一系列多個類型的抽象子類,更好的利用了工廠子類执庐,適合更加復(fù)雜的業(yè)務(wù)需求酪耕。抽象工廠類的方法定義也和工廠方法模式不太一樣,由于工廠方法模式只創(chuàng)建一個抽象子類轨淌,所以直接用的類方法定義迂烁,抽象方法模式可能會創(chuàng)建多個類型的抽象子類,所以用的實例方法定義递鹉。
普通方式代碼實現(xiàn)
這里代碼實現(xiàn)按照上面舉的例子盟步,代碼結(jié)構(gòu)也完全按照上面UML類圖中畫的結(jié)構(gòu),使整篇文章可以更加統(tǒng)一躏结,更深刻的理解這個設(shè)計模式却盘。
代碼量比較多,但是為了更好的體現(xiàn)出抽象工廠模式媳拴,所以就全貼出來了黄橘。
首先創(chuàng)建兩個Model類,這兩個Model類并不屬于抽象工廠模式結(jié)構(gòu)的一部分屈溉,只是為了更好的體現(xiàn)出面向模型開發(fā)塞关。
@interface User : NSObject
@property (nonatomic, copy ) NSString *userName;
@property (nonatomic, assign) NSInteger userAge;
@end
@implementation User
@end
@interface City : NSObject
@property (nonatomic, copy) NSString *cityName;
@property (nonatomic, copy) NSString *cityCode;
@end
@implementation City
@end
用戶信息系列相關(guān)類
@interface UserInfo : NSObject
- (void)setUserName:(User *)name;
@end
@implementation UserInfo
- (void)setUserName:(User *)name {}
@end
@interface SqliteUserInfo : UserInfo
@end
@implementation SqliteUserInfo
- (void)setUserName:(User *)name {
NSLog(@"這里編寫數(shù)據(jù)庫持久化方案");
}
@end
@interface CoreDataUserInfo : UserInfo
@end
@implementation CoreDataUserInfo
- (void)setUserName:(User *)name {
NSLog(@"這里編寫CoreData持久化方案");
}
@end
搜索信息系列相關(guān)類
@interface SearchInfo : NSObject
- (void)setSearchCity:(City *)city;
@end
@implementation SearchInfo
- (void)setSearchCity:(City *)city {}
@end
@interface SqliteSearchInfo : SearchInfo
@end
@implementation SqliteSearchInfo
- (void)setSearchCity:(City *)city {
NSLog(@"這里編寫數(shù)據(jù)庫持久化方案");
}
@end
@interface CoreDataSearchInfo : SearchInfo
@end
@implementation CoreDataSearchInfo
- (void)setSearchCity:(City *)city {
NSLog(@"這里編寫CoreData持久化方案");
}
@end
設(shè)置信息系列相關(guān)類
@interface SettingsInfo : NSObject
- (void)resetAllSettings;
@end
@implementation SettingsInfo
- (void)resetAllSettings {}
@end
@interface SqliteSettingsInfo : SettingsInfo
@end
@implementation SqliteSettingsInfo
- (void)resetAllSettings {
NSLog(@"重置數(shù)據(jù)庫設(shè)置信息");
}
@end
@interface CoreDataSettingsInfo : SettingsInfo
@end
@implementation CoreDataSettingsInfo
- (void)resetAllSettings {
NSLog(@"重置CoreData設(shè)置信息");
}
@end
工廠抽象相關(guān)類
@interface Factory : NSObject
- (UserInfo *)CreateUserInfo;
- (SearchInfo *)CreateSearchInfo;
- (SettingsInfo *)CreateSettingsInfo;
@end
@implementation Factory
- (UserInfo *)CreateUserInfo {
return nil;
}
- (SearchInfo *)CreateSearchInfo {
return nil;
}
- (SettingsInfo *)CreateSettingsInfo {
return nil;
}
@end
@interface SqliteFactory : Factory
@end
@implementation SqliteFactory
- (UserInfo *)CreateUserInfo {
return [SqliteUserInfo new];
}
- (SearchInfo *)CreateSearchInfo {
return [SqliteSearchInfo new];
}
- (SettingsInfo *)CreateSettingsInfo {
return [SqliteSettingsInfo new];
}
@end
@interface CoreDataFactory : Factory
@end
@implementation CoreDataFactory
- (UserInfo *)CreateUserInfo {
return [CoreDataUserInfo new];
}
- (SearchInfo *)CreateSearchInfo {
return [CoreDataSearchInfo new];
}
- (SettingsInfo *)CreateSettingsInfo {
return [CoreDataSettingsInfo new];
}
@end
外界使用
- (void)viewDidLoad {
User *user = [User new];
City *city = [City new];
Factory *factory = [SqliteFactory new];
UserInfo *userInfo = [factory CreateUserInfo];
SearchInfo *searchInfo = [factory CreateSearchInfo];
SettingsInfo *settingsInfo = [factory CreateSettingsInfo];
[userInfo setUserName:user];
[searchInfo setSearchCity:city];
[settingsInfo resetAllSettings];
}
到此為止我們就編寫完抽象工廠設(shè)計模式的代碼了,上面抽象工廠模式的示例中定義了三個類型的抽象類UserInfo
子巾、SearchInfo
帆赢、SettingsInfo
驶睦,抽象子類分別繼承不同類型的抽象類,并實現(xiàn)不同系列的持久化代碼匿醒。這三個類型的抽象類中定義了兩種不同的數(shù)據(jù)持久化方案场航,分別是Sqlite
存儲和CoreData
存儲,這就是兩種數(shù)據(jù)持久化系列廉羔,分別用SqliteFactory
和CoreDataFactory
表示這兩個系列溉痢。
代碼中定義了抽象工廠類Factory
類,并定義了三個抽象接口用來實例化不同類型的抽象子類憋他,兩個工廠子類SqliteFactory
和CoreDataFactory
繼承自抽象工廠類孩饼,內(nèi)部分別實現(xiàn)了兩種不同系列的抽象子類實例化,例如SqliteFactory
中會實例化關(guān)于Sqlite
存儲方式的抽象子類竹挡,并通過抽象工廠類中定義的抽象接口返回給外界使用镀娶。
統(tǒng)一控制工廠子類的切換
這三種工廠設(shè)計模式中除了簡單工廠模式,工廠方法模式和抽象工廠模式都需要外界實例化不同的工廠子類揪罕,這種在外界實例化工廠子類的代碼可能會出現(xiàn)在多個地方梯码,而在很多業(yè)務(wù)需求中都需要我們統(tǒng)一切換某個功能,從代碼上來說就是切換工廠子類好啰,怎樣可以做到統(tǒng)一切換工廠子類的需求呢轩娶?
就拿上面的持久化方案的例子來說,我們定義了兩種持久化方案框往,通過SqliteFactory
和CoreDataFactory
工廠子類來創(chuàng)建不同的持久化方案鳄抒。假設(shè)現(xiàn)在我們項目比較龐大,代碼量比較多椰弊,并且在多個地方用到了SqliteFactory
工廠子類许溅,現(xiàn)在需求是切換為CoreDataFactory
的持久化方案,我們應(yīng)該怎樣快速的切換持久化方案秉版?
其實我們可以通過typedef
定義別名的方式切換工廠子類贤重,在其他地方只需要使用我們typedef
定義的別名就可以,例如下面代碼就可以做到修改一處typedef
定義沐飘,就修改了整個項目的持久化方案游桩。
還是按照上面的抽象工廠模式的代碼,這里只寫出外界使用的代碼部分
typedef SqliteFactory SaveFactory; //定義的工廠子類別名
@implementation TestTableViewController
- (void)viewDidLoad {
User *user = [User new];
City *city = [City new];
Factory *factory = [SaveFactory new];
UserInfo *userInfo = [factory CreateUserInfo];
SearchInfo *searchInfo = [factory CreateSearchInfo];
SettingsInfo *settingsInfo = [factory CreateSettingsInfo];
[userInfo setUserName:user];
[searchInfo setSearchCity:city];
[settingsInfo resetAllSettings];
}
從上面的代碼可以看到耐朴,我們定義了一個SaveFactory
的工廠子類別名借卧,下面直接通過這個別名進行的工廠子類的實例化。因為如果存儲相同的內(nèi)容筛峭,項目中只會出現(xiàn)一種持久化方案铐刘,所以我們只需要修改typedef
的定義,就可以切換整個項目的持久化方案影晓。
配合反射機制優(yōu)化代碼
對于抽象工廠模式的反射機制镰吵,實現(xiàn)方式和之前的簡單工廠模式不太一樣檩禾,我采用的是預(yù)編譯指令加常量字符串類名反射的方式實現(xiàn)的。別的不多說疤祭,先上代碼來看看盼产,我這里貼出了主要代碼,其他一樣的地方我就不往外貼了勺馆,不浪費大家時間戏售。
還是按照上面的業(yè)務(wù)場景,我定義了兩種同名不同值的字符串常量草穆,這些常量字符串對應(yīng)的就是抽象子類的類名灌灾,一個條件分支就是一個系列的抽象子類,通過預(yù)編譯指令#if
來進行不同系列的抽象子類間的統(tǒng)一切換悲柱,定義了SAVE_DATA_MODE_SQLITE
宏定義來控制系列的切換锋喜。這種定義方式可以更方便的進行不同系列間的切換,從使用上來看非常像我們用預(yù)編譯指令替換了之前的工廠子類豌鸡,實際上從代碼的角度上來說這種方式對系列間的切換更加統(tǒng)一和方便嘿般。
#define SAVE_DATA_MODE_SQLITE 1
#if SAVE_DATA_MODE_SQLITE
static NSString * const kUserInfoClass = @"SqliteUserInfo";
static NSString * const kSearchInfoClass = @"SqliteSearchInfo";
static NSString * const kSettingsInfoClass = @"SqliteSettingsInfo";
#else
static NSString * const kUserInfoClass = @"CoreDataUserInfo";
static NSString * const kSearchInfoClass = @"CoreDataSearchInfo";
static NSString * const kSettingsInfoClass = @"CoreDataSettingsInfo";
#endif
下面是工廠類的定義,使用反射機制的抽象工廠模式刨除了工廠子類直颅,只用一個工廠類來進行操作子類的實例化博个,這種方式和之前的簡單工廠模式非常相似。不同的是之前的簡單工廠模式只需要初始化一個類型的抽象子類功偿,而抽象工廠模式需要初始化多個類型的抽象子類。
由于我們采用了反射機制往堡,并且由預(yù)編譯指令進行系列間的切換械荷,所以這里就直接使用類方法了,哪里用就直接實例化抽象子類即可虑灰,不存在工廠子類之間的選擇問題了吨瞎。
@interface Factory : NSObject
+ (UserInfo *)CreateUserInfo;
+ (SearchInfo *)CreateSearchInfo;
+ (SettingsInfo *)CreateSettingsInfo;
@end
@implementation Factory
+ (UserInfo *)CreateUserInfo {
return [[NSClassFromString(kUserInfoClass) alloc] init];
}
+ (SearchInfo *)CreateSearchInfo {
return [[NSClassFromString(kSearchInfoClass) alloc] init];
}
+ (SettingsInfo *)CreateSettingsInfo {
return [[NSClassFromString(kSettingsInfoClass) alloc] init];
}
@end
通過這種方式進行不同系列的切換,只需要修改一個宏定義的值即可穆咐,也就是SAVE_DATA_MODE_SQLITE
后面的1切換為0的步驟颤诀,這種方式是符合我們開放封閉原則的。以后每個系列增加新的類型后对湃,只需要將新增加的兩個類名對應(yīng)添加在預(yù)編譯指令中崖叫,在工廠方法中擴展一個實例化新類型的方法即可。這種方式對擴展是開放的拍柒,對修改是關(guān)閉的心傀。
對于上面的示例代碼的編寫需要注意一下,按照蘋果的命名規(guī)范拆讯,常量的作用域如果只在一個類中脂男,前面就用小寫k修飾养叛,如果修飾的常量在其他類中用到,也就是.h
文件中用extern
修飾的常量宰翅,不需要用小寫k修飾弃甥。我們在蘋果的很多官方代碼和Kit
中也可以看到相同的定義,宏定義也是相同的規(guī)則汁讼。(extern
修飾的常量在.m
中不要用static
修飾)
項目中如果用到任何預(yù)編譯指令潘飘,在修改重新運行前,一定要clear
一下掉缺,清除緩存卜录,否則會因為緩存導(dǎo)致bug。
抽象工廠模式的優(yōu)缺點
優(yōu)點
抽象工廠模式正如其名字一樣眶明,理解起來非常抽象艰毒,正是因為這種抽象,使得抽象工廠模式非常強大和靈活搜囱,比其他兩種工廠設(shè)計模式要強大很多丑瞧。抽象工廠模式可以創(chuàng)建多個系列,并且每個系列抽象子類一一對應(yīng)蜀肘,這種強大的功能是其他兩種工廠模式都不能實現(xiàn)的绊汹。
通過抽象工廠模式統(tǒng)一控制多個系列的抽象子類,可以用多個系列的抽象子類完成一些復(fù)雜的需求扮宠。例如我們文中說到的本地持久化方案的切換西乖,最后通過我們的不斷優(yōu)化,做到只需要修改一個預(yù)編譯指令的參數(shù)即可切換整個數(shù)據(jù)持久化方案坛增,這是其他工廠模式所不能完成的获雕。
抽象工廠模式延續(xù)了工廠模式的優(yōu)點,外界接觸不到任何類型的抽象子類收捣,而只需要知道不同類型的抽象類即可届案,抽象子類的創(chuàng)建過程都在工廠子類中。這種設(shè)計方式充分的利用了面向?qū)ο笳Z言中的多態(tài)特性罢艾,使靈活性大大提升楣颠。而且抽象工廠模式是非常符合開放封閉原則的,對擴展的開放以及對修改的封閉都完美支持咐蚯。
缺點
抽象工廠模式帶來的缺點也是顯而易見的童漩,最明顯的缺點就是模式比較龐大,所以需要在適合的業(yè)務(wù)場景使用這種模式仓蛆,否則會適得其反睁冬。
工廠模式三部曲總結(jié)
示例
到目前為止,工廠模式三部曲中的三種工廠模式都已經(jīng)講完了,在這里我們將簡單回顧和總結(jié)一下這三種設(shè)計模式豆拨。首先直奋,我將根據(jù)三種工廠模式畫三張同樣需求的UML類圖,看完這三張類圖大家就對三種工廠模式清晰明了了施禾。
需求就以現(xiàn)在比較火的樂視系列的樂視TV脚线、樂視手機,小米系列的小米TV弥搞、小米手機來作為需求邮绿,這三張圖主要體現(xiàn)工廠模式的整體架構(gòu)。
從這三張圖中可以看出攀例,簡單工廠模式和工廠方法模式對應(yīng)的是同一類型的操作結(jié)構(gòu)船逮,在當前例子中就是手機類型,因為只有一個類型粤铭,所以還沒有系列的概念挖胃。在需求不太復(fù)雜,并且不需要多個系列間的切換時梆惯,可以考慮使用這兩種設(shè)計模式酱鸭。
之前的業(yè)務(wù)只有手機一種類型,在業(yè)務(wù)復(fù)雜之后出現(xiàn)了一個新類型的產(chǎn)品-電視垛吗,這時候工廠類就需要增加一種類型凹髓。由于需求更加復(fù)雜,這時候就出現(xiàn)了系列的概念(之前工廠方法模式中類型單一怯屉,所以不需要系列的概念)蔚舀,樂視系列和小米系列,工廠子類變成了每個工廠子類對應(yīng)一個系列的設(shè)計蚀之,每個系列中對應(yīng)不同類型的產(chǎn)品蝗敢。
抽象工廠模式對應(yīng)多個類型的操作結(jié)構(gòu),分屬于不同的系列足删。這種結(jié)構(gòu)比較適合復(fù)雜的業(yè)務(wù)需求,例如文中將的Sqlite
數(shù)據(jù)庫和CoreData
兩種存儲方式的切換锁右,通過抽象工廠模式就非常好實現(xiàn)失受。
工廠模式總結(jié)
在這三種設(shè)計模式中都有一個共同的特點,就是繼承自抽象類的抽象子類或工廠子類咏瑟,都必須對抽象類定義的方法給出對應(yīng)的實現(xiàn)(可以相同拂到,也可以不同),這種模式才叫做工廠模式码泞。工廠模式的核心就是抽象和多態(tài)兄旬,抽象子類繼承自抽象類,對抽象類中定義的方法和屬性給出不同的實現(xiàn)方式,通過多態(tài)的方式進行方法實現(xiàn)和調(diào)用领铐,構(gòu)成了工廠模式的核心悯森。
在工廠類中對開放封閉原則有著完美的體現(xiàn),對擴展的開放以及對修改的封閉绪撵。例如最抽象的抽象工廠模式瓢姻,抽象工廠模式中增加新的系列,直接擴展一個工廠子類及對應(yīng)的抽象子類音诈,對整個模式框架不會帶來其他影響幻碱。如果增加一個新的類型,創(chuàng)建新的類型對應(yīng)的類细溅,并對整個抽象工廠類及其子類進行方法擴展褥傍。
在外界使用抽象子類的功能時,不需要知道任何關(guān)于抽象子類的特征喇聊,抽象子類也不會出現(xiàn)在外界恍风,外界只需要和抽象類打交道就可以。工廠模式將抽象子類的創(chuàng)建和實現(xiàn)分離承疲,具體的創(chuàng)建操作由工廠類來進行邻耕,抽象子類只需要關(guān)注業(yè)務(wù)即可,外界不需要知道抽象子類實例化的過程燕鸽。這種方式非常靈活并易于擴展兄世,而且在大型項目中尤為明顯,可以很好的避免代碼量過多的問題啊研。
對于這三種工廠模式的選擇御滩,我建議如果是像Sqlite
數(shù)據(jù)庫和CoreData
切換,這樣業(yè)務(wù)中存在多個系列的需求党远,使用抽象工廠模式削解。如果比較簡單的創(chuàng)建單個類型的抽象子類,這種方式建議用簡單工廠模式或工廠方法模式沟娱。三種設(shè)計模式的選擇還是要看需求和項目復(fù)雜度氛驮,用得好的話可以給代碼帶來極大的靈活性和擴展性。
總結(jié)
設(shè)計模式主要是一種思想方面的東西济似,沒有任何一種設(shè)計模式是萬能的矫废,并適應(yīng)于各種業(yè)務(wù)場景的設(shè)計模式。所以在不同的地方使用對應(yīng)的設(shè)計模式砰蠢,或者說根據(jù)業(yè)務(wù)需要設(shè)計一種適合當前業(yè)務(wù)場景的設(shè)計模式蓖扑,這才是最理想的設(shè)計模式用法。
前段時間寫了關(guān)于工廠模式的系列文章台舱,這系列文章理解起來比較難懂律杠。應(yīng)廣大讀者的需要,這段時間專門給這系列文章補了Demo
。
Demo
只是來輔助讀者更好的理解文章中的內(nèi)容柜去,應(yīng)該博客結(jié)合Demo
一起學(xué)習(xí)灰嫉,只看Demo
還是不能理解更深層的原理。Demo
中代碼都會有注釋诡蜓,各位可以打斷點跟著Demo
執(zhí)行流程走一遍熬甫,看看各個階段變量的值。
Demo地址:劉小壯的Github