1. 程式人生 > >Builder Pattern在IOS的實際應用

Builder Pattern在IOS的實際應用

在說 Builder Pattern 之前,我們先來看看一個場景。假設我們要預定一個 iPhone 6,要 64G 的,金色的,用程式碼表述大概是這樣:

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

也可以是另一種方式

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

實際上,以上兩種方式分別代表了兩種iOS物件的初始化方式。在未使用Builder Pattern之前,這兩種初始化物件方式都有不方便的地方。第一種方法靈活,但是如果你接觸iOS時間長點就會發現,經常會記不住這個類到底有哪些property需要初始化,尤其是當這個類是被人提供給你的時候!我們多麼希望類的提供者能搞點註釋啊啥的告知我們一下。第二種方法則很清晰地告訴呼叫者到底有哪些property需要在建立物件時初始化。但是,當類的提供者有天跟你說:hey,哥們,現在業務邏輯改變了,我增加了一個xxx屬性,init方法也變了。這時,你是不是很想打他?每新增一個新的屬性,init方法就要變動,而且當需要初始化的屬性多大十幾二十個時,這個init方法要不要太壯觀!

所以,當某個類的屬性值很多時,我們可以考慮使用建造者模式Builder Pattern來讓初始化過程清晰一些,類的使用者會很感恩你這麼做的。用iOS描述大概是這樣的:

WSiPhone6 *iphone6 = [WSiPhone6 createWithBuilder:^(WSiPhone6Builder *builder) {
        builder.color = @"red";
        builder.storage = 64;
        builder.place = @"香港";
    }];
 NSLog(@"iphone6:%@",iphone6);
+(instancetype)createWithBuilder:(BuilderBlock)block
{
    NSParameterAssert(block != nil);
    WSiPhone6Builder *builder = [WSiPhone6Builder new];
    block(builder);
    return [builder build];
}
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class WSiPhone6;
@class WSiPhone6Builder;

typedef void(^BuilderBlock)(WSiPhone6Builder *);
NS_ASSUME_NONNULL_BEGIN

@interface WSiPhone6Builder : NSObject
@property (nonatomic,strong)UIColor *color;
@property (nonatomic,assign)NSInteger storage;
@property (nonatomic,copy)NSString *place;
@property (nonatomic,copy)NSString *size;
- (WSiPhone6 *)build;

@end

NS_ASSUME_NONNULL_END
#import "WSiPhone6Builder.h"
#import "WSiPhone6.h"

@implementation WSiPhone6Builder

-(WSiPhone6 *)build
{
    NSAssert(self.color, @"尺寸別忘記填寫了");
    
    WSiPhone6 *iphone6 = [[WSiPhone6 alloc] init];
    iphone6.color = self.color;
    iphone6.storage = self.storage;
    iphone6.place = self.place;
    return iphone6;
    
    //return [[WSiPhone6 alloc] initWithBuilder:self];
}

@end

一些需要呼叫者強制初始化的引數可以build函式的開頭處新增斷言,一旦WSiPhone6Builder類的呼叫者在初始化時沒有初始化color就是斷言失敗丟擲異常。這在多人協同開發時可以省事很多。

然後發現IOS原生的UIAlertContoller也採用類似這種回撥設定模式:

 UIAlertController *alerController = [UIAlertController alertControllerWithTitle:@"title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
    [alerController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        
    }];