iOS常用設計模式之一——工廠方法(簡單工廠模式,工廠方法模式, 抽象工廠模式)

先開個小頭,明天寫出來,不逼著自己是不會干活的。



題外話:

首先,設計模式是什么,為什么要用設計模式,設計模式用來做什么?

設計模式是什么?

In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design. It is a description or template for how to solve a problem that can be used in many different situations. Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.

對于一些經(jīng)常出現(xiàn)的具有相似特征的問題,設計一個模式,來解決問題,這個模式具有可移植性,對于不同的問題有高度的抽象解決方法。

為什么用設計模式?

程序之美在與簡潔,優(yōu)雅,易擴展,易維護,可復用,封閉性與開放性兼具。利用設計模式可以達到這些目的。

設計模式用來做什么?

當我們的問題可以抽象成用某個模式,可以利用現(xiàn)有的設計模式來組織我們的代碼。

常見的設計模式有:單例模式,委托模式,工廠設計模式,協(xié)議等等。



進入正題:

簡單工廠模式

專門定義一個類負責創(chuàng)建其他類的實例,被創(chuàng)建的類通常具有共同的父類。

簡單工廠模式的UML圖


圖1

簡單工廠模式的角色:

工廠,接受客戶端的請求,通過請求負責創(chuàng)建相應的產(chǎn)品對象。

抽象產(chǎn)品,工廠模式所創(chuàng)建對象的父類或者共同擁有的接口??梢允浅橄箢惢蚪涌?。

具體產(chǎn)品,工廠模式所創(chuàng)建的對象都是它的實例。


簡單工廠模式的主要實現(xiàn)

+(Product *)createProductWithType:(ProductType)type {

? ? switch(type){

? ? ? ? case ProductTypeOne:

? ? ? ? ? ? return[[ProductOne alloc]init];

? ? ? ? ? ? break;

? ? ? ? case ProductTypeTwo:

? ? ? ? ? ? return[[ProductTwo alloc]init];

? ? ? ? ? ? break;

? ? ? ? case ProductTypeThree:

? ? ? ? ? ? return[[ProductThree alloc]init];

? ? ? ? ? ? break;

? ? ? ? default:

? ? ? ? ? ? break;

? ? }

? ? return nil;

}


簡單工廠模式的主要缺點:

簡單工廠模式不僅對擴展開放,而且對修改也開放,所以違反了“開放-關閉原則”。說人話:當需要擴展一個產(chǎn)品時,不僅需要新建一個產(chǎn)品類,同時還要修改工廠方法。另外,所有產(chǎn)品對象創(chuàng)建的邏輯都被集中到了工廠類中,并不優(yōu)雅。

工廠方法

和簡單工廠方法相比,工廠方法的改進:將工廠類也抽象為了抽象工廠類和工廠子類,外界調(diào)用更加靈活,這也是對多態(tài)的一種體現(xiàn)。具體產(chǎn)品的生成分布到具體工廠中實現(xiàn)。

具體產(chǎn)品繼承抽象產(chǎn)品,具體工廠繼承抽象工廠。

//抽象產(chǎn)品

@interfaceProduct:NSObject

@end

@implementationProduct

@end

//具體產(chǎn)品1

@interfaceProductOne:Product

@end

@implementationProductOne

@end

//具體產(chǎn)品2

@interfaceProductTwo:Product

@end

@implementationProductTwo

@end

//抽象工廠

@interfaceFactory:NSObject

+(Product*)createProduct;

@end

@implementationFactory

+(Product*)createProduct

{

return [[Product alloc]init];

//如果Product是抽象的,那么這里可以返回nil

}

@end

//具體產(chǎn)品1的具體工廠

@interfaceProductOneFactory:Factory

+(Product*)createProduct;

@end

@implementationProductOneFactory

+(Product*)createProduct

{

return[[ProductOne alloc]init];

}@end

//具體產(chǎn)品2的具體工廠

@interfaceProductTwoFactory:Factory

+(Product*)createProduct;

@end

@implementationProductTwoFactory

+(Product*)createProduct

{

return[[ProductTwo alloc]init];

}

@end

//客戶端調(diào)用

Product*p=[ProductOneFactory createProduct];

NSLog(@"%@",p);

Product*p2=[ProductTwoFactory createProduct];

NSLog(@"%@",p2);


優(yōu)點

工廠方法模式的的優(yōu)點在于更大的靈活性,增加或刪除某個產(chǎn)品都不會對其他地方造成影響,更佳符合開放封閉原則。

而且對抽象的使用更佳深入,將工廠類也抽象為了抽象工廠類和工廠子類,外界調(diào)用更加靈活,這也是對多態(tài)的一種體現(xiàn)。

缺點

工廠方法模式的缺點也是非常顯而易見的,工廠方法模式中新增一個抽象子類,意味著工廠子類要跟著成對增加(OC中要x4),這樣會造成生成過多的類,工廠方法模式的復雜度也會隨之增加。



抽象工廠模式


抽象工廠模式和工廠方法模式很相似,但是抽象工廠模式將抽象發(fā)揮的更加極致,是三種工廠模式中最抽象的一種設計模式

抽象工廠模式中定義了抽象工廠類,抽象工廠類中定義了每個系列的抽象子類創(chuàng)建所需的方法,這些方法對應著不同類型的抽象子類實例化過程。每個工廠子類都對應著一個系列,工廠子類通過重寫這些方法來實例化當前系列的抽象子類。

抽象工廠模式與工廠方法模式

兩者都用于相同的目的:創(chuàng)建對象而不讓客戶端知道返回了什么確切的具體對象。

在工廠方法模式中,工廠子類負責抽象子類的實例化,每個工廠子類對應著一個抽象子類,且具有唯一性。而在抽象工廠模式中,一個工廠子類代表一個系列,工廠子類根據(jù)當前系列對不同類型的抽象子類進行創(chuàng)建。工廠方法模式中工廠子類對應的是一個類型的抽象子類,抽象工廠模式對應的是一個系列的抽象子類。


簡單說:工廠方法模式是針對單個類型的抽象類,而抽象工廠模式是針對具有相同結構的一系列類型的抽象類。



圖2



//抽象工廠

@interfaceBrandingFactory:NSObject

+(BrandingFactory*)factory;

-(Hatchback*)createHatchback;

-(SUV*)createSUV;

@end

@implementationBrandingFactory

+(BrandingFactory*)factory

{

if([[self class]isSubclassOfClass:[ToyotaBrandingFactory class]]){

return[[ToyotaBrandingFactory alloc]init];

}else if([[self class]isSubclassOfClass:[FordBrandingFactory class]]){

return[[FordBranding Factory alloc]init];

}else

{

return nil;

}

}

-(Hatchback*)createHatchback

{

return nil;

}

-(SUV*)createSUV

{

return nil;

}

@end

// 具體工廠

@interfaceFordBrandingFactory:BrandingFactory

@end

@implementationFordBrandingFactory

-(Hatchback*)createHatchback

{

FordHatchback*hatchback=[[FordHatchback alloc]init];

return hatchback;

}

-(SUV*)createSUV

{FordSUV *suv=[[FordSUValloc]init];

return suv;

}

@end

@interfaceToyotaBrandingFactory:BrandingFactory

@end

@implementationToyotaBrandingFactory

-(Hatchback*)createHatchback

{

ToyotaHatchback*hatchback=[[ToyotaHatchback alloc]init];

return hatchback;

}

-(SUV*)createSUV

{

ToyotaSUV*suv=[[ToyotaSUValloc]init];returnsuv;

}

@end

//抽象產(chǎn)品

@interfaceHatchback:NSObject

@end

@implementation Hatchback

@end

@interfaceSUV:NSObject

@end

@implementation SUV

@end

//具體產(chǎn)品

@interfaceFordHatchback:Hatchback

@end

@implementationFordHatchback

@end

@interfaceToyotaHatchback:Hatchback

@end

@implementationToyotaHatchback

@end

@interfaceFordSUV:SUV

@end

@implementationFordSUV

@end

@interfaceToyotaSUV:SUV

@end

@implementationToyotaSUV

@end

Cocoa中的抽象工廠模式

創(chuàng)建NSNumber實例的方式完全符合抽象工廠模式。

創(chuàng)建Cocoa對象有兩種方式:使用先alloc后init的方法,或者使用類中的+ className...方法。在Cocoa的基礎框架中,NSNumber類有很多類方法用于創(chuàng)建各種類型的NSNumber對象。

NSNumber*boolNumber=[NSNumbernumberWithBool:YES];NSNumber*charNumber=[NSNumbernumberWithChar:'a'];NSNumber*intNumber=[NSNumbernumberWithInteger:2];

每個返回的對象屬于代表最初輸入值的不同私有子類。打印如下:

2016-09-0810:30:28.415OCDemo[1164:29635]__NSCFBoolean2016-09-0810:30:28.416OCDemo[1164:29635]__NSCFNumber2016-09-0810:30:28.416OCDemo[1164:29635]__NSCFNumber

接受不同類型的參數(shù)并返回NSNumber實例的類方法是類工廠方法。NSNumber是抽象工廠實現(xiàn)的一個例子?;A框架中抽象工廠的此種特點被稱為“類簇”(Class Cluster)。

類簇是基礎框架中一種常見的設計模式,基于抽象工廠模式的思想。它將若干相關的私有具體工廠子類集合到一個工友的抽象超類指下。例如,“數(shù)”包含了各種數(shù)值類型的完整集合,如字符、整數(shù)、浮點數(shù)和雙精度輸。這些數(shù)值類型是”數(shù)“的字集。所以NSNumber自然成為這些數(shù)子類型的超類型(super-type)。NSNumber有一系列共有API,定義了各種類型的數(shù)所共有的行為??蛻舳嗽谑褂脮r無需知道NSNumber實例的具體類型。

類簇是抽象工廠的一種形式。比如,NSNumber本身是一個高度抽象的工廠,而NSCFBoolean和NSCFNumber是具體的工廠子類。子類是具體工廠,因為他們重載了NSNumber中聲明的公有工廠方法以生產(chǎn)產(chǎn)品。例如,intValue和boolValue根據(jù)實際NSNumber對象的內(nèi)部值返回一個值,雖說值的數(shù)據(jù)類型可能不同。從這些工廠方法返回的實際值就是抽象工廠模式的最初定義中所說的“產(chǎn)品”。

創(chuàng)建抽象產(chǎn)品的工廠方法與創(chuàng)建抽象工廠的工廠方法之間有個不同點。顯然,像intValue和boolValue這樣的工廠方法,應在具體工廠(NSCFBoolean和NSCFNumber)中重載以返回實際值(產(chǎn)品)。其他像numberWithBool:和numberWithInteger:這樣的工廠方法并不是為了返回產(chǎn)品,而是為了返回能返回產(chǎn)品的工廠,因此它們不應該在具體工廠子類中重載。

其他時限為類簇的基礎類有NSData、NSArray、NSDictionary、NSString。

工廠模式總結

在這三種設計模式中都有一個共同的特點,就是繼承自抽象類的抽象子類或工廠子類,都必須對抽象類定義的方法給出對應的實現(xiàn)(可以相同,也可以不同),這種模式才叫做工廠模式。工廠模式的核心就是抽象和多態(tài),抽象子類繼承自抽象類,對抽象類中定義的方法和屬性給出不同的實現(xiàn)方式,通過多態(tài)的方式進行方法實現(xiàn)和調(diào)用,構成了工廠模式的核心。

在工廠類中對“開放-封閉原則”有著完美的體現(xiàn),對擴展的開放以及對修改的封閉。例如最抽象的抽象工廠模式,抽象工廠模式中增加新的系列,直接擴展一個工廠子類及對應的抽象子類,對整個模式框架不會帶來其他影響。如果增加一個新的類型,創(chuàng)建新的類型對應的類,并對整個抽象工廠類及其子類進行方法擴展。

在外界使用抽象子類的功能時,不需要知道任何關于抽象子類的特征,抽象子類也不會出現(xiàn)在外界,外界只需要和抽象類打交道就可以。工廠模式將抽象子類的創(chuàng)建和實現(xiàn)分離,具體的創(chuàng)建操作由工廠類來進行,抽象子類只需要關注業(yè)務即可,外界不需要知道抽象子類實例化的過程。這種方式非常靈活并易于擴展,而且在大型項目中尤為明顯,可以很好的避免代碼量過多的問題。


大部分摘自:http://ibloodline.com/articles/2016/09/06/factory.html

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374