Builder Pattern 在 Objective-C 中的使用

來源:互聯網
上載者:User

標籤:

在說 Builder Pattern 之前,我們先來看看一個情境。假設我們要預定一個 iPhone 6,要 64G 的,金色的,用代碼錶述大概是這樣

1234 // PFX 是一個首碼,因為直接寫 iPhone6 不符合類名大寫的習慣,寫成 IPhone6 更是怪異 ╮(╯▽╰)╭PFXiPhone6 *iphone = [[PFXiPhone6 alloc] init];iphone.storage = 64;iphone.color = [UIColor goldenColor];

也可以是另一種方式

1 PFXiPhone6 *iPhone = [[PFXiPhone6 alloc] initWithStorage:64 color:[UIColor goldenColor]];

第一種方式可擴充性好些,但無法約束必須設定某些 property。第二種方式修正了這個問題,但擴充性也差了。

假如又有了新需求,要讓客戶可以選擇發售地區,比如港行,國行,美版等等。對於第一種,自然可以新增一個屬性,但使用者很可能完全不知道新增了這麼個屬性。對於第二種,則只能再建立一個初始化方式,如 -[initWithStorage:color:place]。那如果又有新的需求,比如選擇是否刻字,以及刻哪些字呢?或者可以選擇外殼的種類等等。這兩種方式都不能很好地處理需求的變更。

現在我們來說說 Builder Pattern,這個模式可以在各種語言裡被很方便地實現,比如 javascript

12345 new PFXiPhone6Builder()  .setStorage(64)  .setColor(‘golden‘)  .setPlace(‘HK‘)  .build();

當有新的屬性時,再加一個 setProperty 即可。如果漏寫了某個屬性,可以在 build 裡檢查。

在 Objective-C 裡,這樣的鏈式寫法不是很流行(Masonry裡這種寫法用的比較多),所以,在 OC 裡寫起來大概會是這樣

12345 PFXiPhone6Builder *builder = [[PFXiPhone6Builder alloc] init];builder.storage = 64;builder.color = [UIColor goldenColor];builder.place = @"HK";PFXiPhone6 *iphone = [builder build];

如果少了什麼屬性,在 build 時檢查下即可。這樣既解決了不方便擴充的問題,當有新的屬性時也可以知道。

不過看起來還是不夠優雅,這個 builder 只是一個臨時工具,用完了就扔掉了,既然這樣,那有沒有可能寫法上符合 OC 的傳統,又讓這個 builder 「臨時出現」一下?且看下面這段代碼

12345 PFXiPhone6 *iPhone6 = [PFXiPhone6 createWithBuilder:^(PFXiPhone6Builder *builder){    builder.storage = 64;    builder.color = [UIColor goldenColor];    builder.place = @"HK";}];

是不是看起來舒服多了。builder 只是在 block 範圍內起作用,不會影響當前 context 的變數。這個 +[createWithBuilder:] 的代碼如下

123456 + (instancetype)createWithBuilder:(BuilderBlock)block {    NSParameterAssert(block);    PFXiPhone6Builder *builder = [[PFXiPhone6Builder alloc] init];    block(builder);    return [builder build];}

這裡 build 方法,也有兩種實現,第一種

1234567891011121314 // PFXiPhone6Builder- (PFXiPhone6 *)build{    return [[PFXiPhone6 alloc] initwithBuilder:self];}// PFXiPhone6- (instancetype)initwithBuilder:(PFXiPhone6Builder *)builder{    if (self = [super init]) {        _storage = builder.storage;        _color = builder.color;        _place = builder.place;    }}

另外一種是把兩個過程合并為一個過程

1234567891011 // PFXiPhone6Builder- (PFXiPhone6 *)build{    // 可以在這裡對 property 做檢查    NSAssert(self.place, @"發行區別忘了填哦");    PFXiPhone6 *iphone6 = [[PFXiPhone6 alloc] init];    iPhone6.storage = self.storage;    iPhone6.color = self.color;    iPhone6.place = self.place;    return iPhone6;}

這兩種方式的區別在於對參數的處理,前一個是在目標 Class 中處理,後一種是在 Builder 中處理。

在 Facebook 的 pop 中也有類似的使用,如

123456 POPAnimatableProperty *animatableProperty = [POPAnimatableProperty propertyWithName:@"property" initializer:^(POPMutableAnimatableProperty *prop) {    prop.writeBlock = ^(id obj, const CGFloat values[]) {    };    prop.readBlock = ^(id obj, CGFloat values[]) {    };}];

這裡的 initializer 其實就是 builder

我在寫蘑菇街的基礎架構時,也有用到過幾處,覺得還是蠻方便的,尤其對使用者來說。比如這個可以橫向或縱向滾動的包含可點擊 Items 的 collectionView。

1234567891011121314 self.collectionView = [MGJFlowCollectionView collectionViewWithBuilder:^(MGJFlowCollectionViewBuilder *builder) {    builder.scrollDirection = UICollectionViewScrollDirectionHorizontal;    builder.minimumInteritemSpacing = 10;    builder.minimumLineSpacing = 10;    builder.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);    CGSize itemSize = CGSizeMake(81, 100);    builder.itemSize = itemSize;    builder.dataSource = @[@1,@2,@3,@4,@5,@6, @7,@8, @9, @10];    builder.cellBuilder = ^UIView *(NSNumber *number){        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemSize.width, itemSize.height)];        view.backgroundColor = [UIColor mgj_random];        return view;    };}];

這樣就能通過簡單的配置來產生一個水平的或垂直的 collectionView 了。

使用 Builder Pattern 還有一個好處,就是可以將零散的配置統一起來。比如要建立一個 CollectionView,我們需要設定 layout,還要設定 layout 的一些屬性,還要設定 DataSource / Delegate 等,現在可以在一個地方統一設定,可讀性上也會好一些。

所以如果遇到需要多個參數,甚至某個參數自己還包含了各種參數時,可以考慮下 Builder Pattern。

Builder Pattern 在 Objective-C 中的使用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.