何爲抽象工廠?設計模式
抽象工廠提供一個固定的接口,用於建立一系列有關聯或相依存的對象,而沒必要指定其具體類或其建立的細節。客戶端與從工廠獲得的具體對象之間沒有耦合。框架
抽象工廠與工廠方法模式的區別spa
抽象工廠與工廠方法模式在許多方面有不少類似之處,以致於咱們經常搞不清楚應該在何時用哪個。兩個模式都用於相同的目的:建立對象而不讓客戶端知曉返回了什麼確切的具體對象。設計
抽象工廠:@、經過對象組合建立抽象產品。@、建立多系列產品。@、必須修改父類的接口才能支持新的產品。日誌
工廠方法:@、經過類繼承建立抽象產品。@、建立一種產品。@、子類化建立並重載工廠方法以建立新產品。code
在Cocoa Touch框架中使用抽象工廠對象
在Cocoa Touch框架中能夠常常看到抽象工廠模式,不少基礎類都採用了這一模式。好比NSNumber。建立NSNumber實例的方式徹底符合抽象工廠模式。繼承
建立對象有兩種方式,使用先alloc再init的方法,或者使用類中的+className...方法。NSNumber類有不少類方法用於建立各類類型的NSNumber對象,以下:接口
NSNumber *boolNumber = [NSNumber numberWithBool:YES]; NSNumber *intNumber = [NSNumber numberWithInt:10]; NSNumber *floatNumber = [NSNumber numberWithFloat:10.0]; NSNumber *doubleNumber = [NSNumber numberWithDouble:10.0];
每一個返回的對象屬於表明最初輸入值的不一樣私有子類,能夠用NSLog輸出它們類的描述:ip
NSLog(@"%@", [[boolNumber class] description]); NSLog(@"%@", [[intNumber class] description]); NSLog(@"%@", [[floatNumber class] description]); NSLog(@"%@", [[doubleNumber class] description]);
將看到以下的日誌信息:
2015-09-06 21:25:13.116 NSNumberDemo[59970:4475507] __NSCFBoolean 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber 2015-09-06 21:25:13.117 NSNumberDemo[59970:4475507] __NSCFNumber
除了boolNumber的實際類型是NSCFBoolean之外,大多數實際類爲NSCFNumber類型。儘管這些+className類工廠方法返回NSNumber具體子類的實例,可是返回的實例確實支持NSNumber的公有接口。
雖然它們屬於NSNumber的不一樣具體子類,可是其行爲由抽象超類NSNumber定義,並且是公有的。以下代碼所示:
NSLog(@"%d", [boolNumber intValue]); NSLog(@"%@", [floatNumber boolValue] ? @"YES" : @"NO");
將看到日誌信息以下:
2015-09-06 21:32:59.234 NSNumberDemo[60043:4478868] 1 2015-09-06 21:32:59.234 NSNumberDemo[60043:4478868] YES
boolNumber在內部保持布爾值YES,但仍實現了公有intValue方法,返回其內部布爾值的適當整數值。floatNumber也是如此,它重載了boolValue方法,返回反映其內部浮點型值的適當布爾值。
接受不一樣類型的參數並返回NSNumber實例的類方法是類工廠方法(工廠模式)。NSNumber的類工廠方法生產各類數工廠。numberWithBool:建立NSCFBoolean工廠的實例,而numberWithInt:建立NSCFNumber的實例。NSNumber中的類工廠方法定義了決定實例化何種私有具體子類(好比,NSCFBoolean或NSCFNumber)的默認行爲。這一版本的工廠方法是傳統工廠方法模式的一個變體,此處的抽象產品爲做爲工廠的具體NSNumber子類。NSNumber是抽象工廠實現的一個例子。基礎框架中抽象工廠的此種特色被稱爲類簇。
類簇是基礎框架中一種常見的設計模式,基於抽象工廠模式的思想。它將若干相關的私有具體工廠子類集合到一個公有的抽象超類之下。好比,數包含了各類數值類型的完整集合,如字符、浮點數、整數等。這些數值類型都是數的子集。因此NSNumber天然成爲這些數子類型的超類型。NSNumber有一系列公有API,定義了各類類型的數所共有的行爲。客戶端在使用時無需知道NSNumber實例的具體類型。
類簇是抽象工廠的一種形式。好比,NSNumber自己是一個高度抽象的工廠,NSCFBoolean和NSCFNumber是具體工廠子類。子類是具體工廠,由於它們重載了NSNumber中聲明的公有工廠方法以生產產品。例如,intValue和boolValue根據實際NSNumber對象的內部值返回一個值,雖然值的數據類型可能不一樣。從這些工廠方法返回的實際值就是抽象工廠模式的最初定義中的所說產品。
建立抽象產品的工廠方法與建立抽象工廠的工廠方法之間有個不一樣點。顯然,像intValue和boolValue這樣的工廠方法,應該在具體工廠(NSCFNumber與NSCFBoolean)中重載以返回產品。而像numberWithBool:和numberWithInt:這樣的工廠方法並非爲了返回產品,而是爲了返回能返回產品的工廠,所以它們不該在具體子類重載。
總結
抽象工廠模式是一種極爲常見的設計模式。它是最基本的,由於它能夠涉及許多類型的對象建立。一系列相關的類,應該做爲一種抽象,不爲客戶端所見。抽象工廠則能夠方便的解決這個問題,而不暴露建立過程當中任何沒必要要的細節或所建立對象的確切類型。