設計模式三板斧之--生成器

第一板斧

何爲生成器模式?

生成器模式(Builder): 將一個複雜對象的構建與它的表現分離,使得一樣的構建過程能夠建立不一樣的表現。

what?說啥呢?

舉個例子: 選擇建造本身的房子的人會把工程外包給承包商。單一承包商不能建造整個房子,他將其分解爲幾個部分,而後轉包給幾個實際的建築商,他們懂得如何將零部件組裝起來。房子由由風格、顏色和尺寸各不相同的部件組成。客戶告訴承包商房子裏都要有什麼,而後承包商協調各房屋建築商,決定須要作什麼。應該如何建造,建築商就如何施工。建房子是個複雜過程,單憑一雙手就想建房子,即使可能也很是困難。若是承包商(指導者)與懂得如何建造的建築商相互協調,這一過程簡單得多且更易管理。

解決什麼問題

  • 有時,構建某些對象有多種不一樣方式。若是這些邏輯包含在構建這些對象的類的單一方法中,構建的邏輯就會變得很是複雜(好比,針對各類構建需求的一大片嵌套if-else或者switch-case語句)。若是可以把構建過程分解爲客戶——指導者——生成器的關係,那麼過程將更容易管理與複用。針對此類關係的設計模式稱爲生成器。設計模式

  • 建造者模式是一步一步建立一個複雜的對象,它容許用戶只經過指定複雜對象的類型和內容就能夠構建它們,用戶不須要知道內部的具體構建細節。建造者模式屬於對象建立型模式。根據中文翻譯的不一樣,建造者模式又能夠稱爲生成器模式。ui

  • 若是咱們用了生成器模式,那麼用戶就只需指定須要建造的類型就能夠到帶到它們,而建造的過程和細節就不需知道了。atom

第二板斧

生成器結構

建造者模式包含以下角色:spa

  • Builder:抽象建造者翻譯

    Builder是一個抽象接口,聲明瞭一個buildPart方法,該builder方法由ConcreteBuilder實現,以構造實際產品(Product).
  • ConcreteBuilder:具體建造者設計

  • Director:指揮者code

    Director定義了一個construct方法,命令Builder的實例去buildPart。Director和Builder造成一種聚合關係.
  • Product:產品角色對象

類圖blog

clipboard.png

時序圖繼承

clipboard.png

第三板斧

生成器與抽象工廠的對比

二者有類似之處。可是,一方面生成器關注的是分步建立複雜對象,不少時候同一類型的對象能夠以不一樣的方式建立。另外一方面,抽象工廠的重點在於建立簡單或複雜產品的套件,生成器在多步建立過程的最後一步返回產品,而抽象工廠會當即返回產品

生成器 抽象工廠
構建複雜對象 構件簡單或複雜對象
以多個步驟構建對象 以單一步驟構建對象
以多種方式構建對象 以單一方式構建對象
在構建過程的最後一步返回產品 馬上返回產品
專一一個特定產品 強調一套產品

代碼演示

如今以生產車的例子做演示,這裏的三個角色分別是:
  • Car (Product)

  • CarBuilder (Builder)

  • CarDirector (Director)

用戶須要SUV和小汽車,對應的ConcreteBuilder分別是:
  • SUVCarBuilder

  • SedanCarBuilder

產品 Car
@interface Car : NSObject

@property (nonatomic, assign) NSUInteger wheel; // 輪毅
@property (nonatomic, assign) CGFloat engine; // 發動機
@property (nonatomic, assign) CGFloat chassis; // 底盤
@property (nonatomic, assign) CGSize size; // 車身

/// 跑起來
- (void)run;

@end
建造者 CarBuilder.h
@interface CarBuilder : NSObject

@property (nonatomic, strong) Car *car;

/// 組裝車輪
- (void)buildWheel;

/// 組裝車身
- (void)buildBody;

/// 組裝發動機
- (void)buildEngie;

/// 組裝底盤    
- (void)buildChassis;

/// 獲得產品
- (Car *)getCar;

@end
因爲它是抽象類,iOS中並無抽象類的概念,先這樣實現CarBuilder.m
@implementation CarBuilder

- (instancetype)init
{
    self = [super init];
    if (self) {
        _car = [[Car alloc] init];
    }
    return self;
}

/// 組裝車輪
- (void)buildWheel
{
    NSAssert(NO, @"必須建立具體車輪");
    self.car.wheel = 0;
}

/// 組裝車身
- (void)buildBody
{
    NSAssert(NO, @"必須建立具體車身");
    self.car.size = CGSizeZero;
}

/// 組裝發動機
- (void)buildEngie
{
    NSAssert(NO, @"必須建立具體發動機");
    self.car.engine = 0;
}

/// 組裝底盤
- (void)buildChassis
{
    NSAssert(NO, @"必須建立具體底盤");
    self.car.chassis = 0;
}

/// 獲得產品
- (Car *)getCar
{
    // doSomething...
    return self.car;
}
這裏以生產SUV爲例,小轎車也同樣。SUVBuilder繼承CarBuilder,只需實現這幾個建造方法便可
@implementation SUVCarBuilder

/// 組裝車輪
- (void)buildWheel
{
    self.car.wheel = 20;
}

/// 組裝車身
- (void)buildBody
{
    self.car.size = CGSizeMake(100, 50);
}

/// 組裝發動機
- (void)buildEngie
{
    self.car.engine = 2.5f; 
}

/// 組裝底盤
- (void)buildChassis
{
    self.car.chassis = 30;
}

@end
最後client調用
- (void)viewDidLoad {
    [super viewDidLoad];
    self.carDirdector = [[CarDirector alloc] init];
}

- (IBAction)SUVButtonTap:(id)sender
{
    SUVCarBuilder *SUVBuilder = [[SUVCarBuilder alloc] init];
    self.carDirdector.builder = SUVBuilder;
    Car *SUVCar = [self.carDirdector construct];
    [SUVCar run];
}

- (IBAction)SedanButtonTap:(id)sender
{
    SedanCarBuilder *SedanBuilder = [[SedanCarBuilder alloc] init];
    self.carDirdector.builder = SedanBuilder;
    Car *SedanCar = [self.carDirdector construct];
    [SedanCar run];
}
相關文章
相關標籤/搜索