類簇class cluster

an architecture that groups a number of private, concrete subclasses under a public, abstract superclass. (一個(gè)在共有的抽象超類下設(shè)置一組私有子類的架構(gòu))

Class cluster 是 Apple 對抽象工廠設(shè)計(jì)模式的稱呼

class cluster 的想法很簡單: 使用信息進(jìn)行(類的)初始化處理期間,會使用一個(gè)抽象類(通常作為初始化方法的參數(shù)或者判定環(huán)境的可用性參數(shù))來完成特定的邏輯或者實(shí)例化一個(gè)具體的子類。而這個(gè)"Public Facing(面向公眾的)"類,必須非常清楚他的私有子類,以便在面對具體任務(wù)的時(shí)候有能力返回一個(gè)恰當(dāng)?shù)乃接凶宇悓?shí)例。對調(diào)用者來說只需知道對象的各種API的作用即可。這個(gè)模式隱藏了他背后復(fù)雜的初始化邏輯,調(diào)用者也不需要關(guān)心背后的實(shí)現(xiàn)。

Class clusters 在 Apple 的Framework 中廣泛使用:一些明顯的例子比如 NSNumber 可以返回不同類型給你的子類,取決于 數(shù)字類型如何提供 (Integer, Float, etc...) 或者 NSArray 返回不同的最優(yōu)存儲策略的子類。

這個(gè)模式的精妙的地方在于,調(diào)用者可以完全不管子類,事實(shí)上,這可以用在設(shè)計(jì)一個(gè)庫,可以用來交換實(shí)際的返回的類,而不用去管相關(guān)的細(xì)節(jié),因?yàn)樗鼈兌甲駨某橄蟪惖姆椒ā?/p>

** 我們的經(jīng)驗(yàn)是使用類簇可以幫助移除很多條件語句。 **

一個(gè)經(jīng)典的例子是如果你有為 iPad 和 iPhone 寫的一樣的 UIViewController 子類,但是在不同的設(shè)備上有不同的行為。

比較基礎(chǔ)的實(shí)現(xiàn)是用條件語句檢查設(shè)備,然后執(zhí)行不同的邏輯。雖然剛開始可能不錯(cuò),但是隨著代碼的增長,運(yùn)行邏輯也會趨于復(fù)雜。 一個(gè)更好的實(shí)現(xiàn)的設(shè)計(jì)是創(chuàng)建一個(gè)抽象而且寬泛的 view controller 來包含所有的共享邏輯,并且對于不同設(shè)備有兩個(gè)特別的子例。

通用的 view controller 會檢查當(dāng)前設(shè)備并且返回適當(dāng)?shù)淖宇悺?/p>

@implementation ZOCKintsugiPhotoViewController

- (id)initWithPhotos:(NSArray *)photos
{
    if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) {
        self = nil;

        if ([UIDevice isPad]) {
            self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos];
        }
        else {
            self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];
        }
        return self;
    }
    return [super initWithNibName:nil bundle:nil];
}

@end

這個(gè)子例程展示了如何創(chuàng)建一個(gè)類簇。

  • 使用[self isMemberOfClass:ZOCKintsugiPhotoViewController.class]防止子類中重載初始化方法,避免無限遞歸。當(dāng)[[ZOCKintsugiPhotoViewController alloc] initWithPhotos:photos]被調(diào)用時(shí),上面條件表達(dá)式的結(jié)果將會是True。

  • self = nil的目的是移除ZOCKintsugiPhotoViewController實(shí)例上的所有引用,實(shí)例(抽象類的實(shí)例)本身將會解除分配( 當(dāng)然ARC也好MRC也好dealloc都會發(fā)生在Main Runloop這一次的結(jié)束時(shí))。

  • 接下來的邏輯就是判斷哪一個(gè)私有子類將被初始化。我們假設(shè)在iPhone上運(yùn)行這段代碼并且ZOCKintsugiPhotoViewController_iPhone沒有重載initWithPhotos:方法。這種情況下,當(dāng)執(zhí)行self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];,ZOCKintsugiPhotoViewController將會被調(diào)用,第一次檢查將會在這里發(fā)生,鑒于ZOCKintsugiPhotoViewController_iPhone不完全是ZOCKintsugiPhotoViewController,表達(dá)式[self isMemberOfClass:ZOCKintsugiPhotoViewController.class]將會是False,于是就會調(diào)用[super initWithNibName:nil bundle:nil],于是就會進(jìn)入ZOCKintsugiPhotoViewController的初始化過程,這時(shí)候因?yàn)檎{(diào)用者就是ZOCKintsugiPhotoViewController本身,這一次的檢查必定為True,接下來就會進(jìn)行正確的初始化過程。(NOTE:這里必須是完全遵循Designated initializer 以及Secondary initializer的設(shè)計(jì)規(guī)范的前提下才會其效果的!不明白這個(gè)規(guī)范的可以后退一步熟悉這種規(guī)范在回頭來看這個(gè)說明)

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

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

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