選擇建造本身的房子的人會把工程外包給承包商。單一承包商不能建造整個房子,他將其分解爲幾個部分,而後轉包給幾個實際的建築商,他們懂得如何將零部件組裝起來。房子由由風格、顏色和尺寸各不相同的部件組成。客戶告訴承包商房子裏都要有什麼,而後承包商協調各房屋建築商,決定須要作什麼。應該如何建造,建築商就如何施工。建房子是個複雜過程,單憑一雙手就想建房子,即使可能也很是困難。若是承包商(指導者)與懂得如何建造的建築商相互協調,這一過程簡單得多且更易管理。git
有時,構建某些對象有多種不一樣方式。若是這些邏輯包含在構建這些對象的類的單一方法中,構建的邏輯就會變得很是複雜(好比,針對各類構建需求的一大片嵌套if-else或者switch-case語句)。若是可以把構建過程分解爲客戶——指導者——生成器的關係,那麼過程將更容易管理與複用。針對此類關係的設計模式稱爲生成器。github
何爲生成器模式?算法
除了客戶與其所要的產品,生成器模式還包含兩個重要角色:Director(指導者)和Builder(生成器)。Builder知道究竟如何在缺乏某些特定信息的狀況下建造產品。Director知道Builder應該建造什麼,以參數向其提供缺乏的信息來建造特定產品。雖然Director知道Builder應該建造什麼,這並不意味着Director知道具體Builder到底是什麼。
c#
Builder是一個抽象接口,聲明瞭一個builderPart方法,該方法由ConcreteBuilder實現,以構造實際產品(Product)。ConcreteBuilder有個getResult方法,向客戶端返回構建完畢的Product。Director定義了一個construct方法,命令Builder的實例去buildPart。Director和Builder造成一種聚合關係。這意味着Builder是一個組成部分,與Director結合,以使整個模式運轉,但同時,Director並不負責Builder的生存期。設計模式
生成器模式:將一個複雜對象的構建和它的表現分離,使得一樣的構建過程能夠建立不一樣的表現。ui
什麼時候使用生成器模式?atom
@:須要建立涉及各類部件的複雜對象。建立對象的算法應該獨立於部件的裝配方式。spa
@:構建過程須要以不一樣的方式(好比,部件或表現的不一樣組合)構建對象。設計
生成器模式與抽象工廠的區別code
生成器模式:構建複雜對象,以多個步驟構建對象,以多種方式構建對象,在構建過程的最後一步返回產品,專一一個特定產品。
抽象工廠模式:構建簡單或複雜對象,以單一步驟構建對象,以單一方式構建對象,馬上返回產品,強調一套產品。
生成器模式的應用
經過構建帶有各種角色的追逐遊戲,涉及各種對象、財產或角色的遊戲,其構建過程會至關複雜,能夠經過生成器模式,把構建角色的算法(如何構建角色)與構建什麼角色分離開來。
咱們將以假想的追逐遊戲爲例,演示如何實現生成器模式。假定有兩種類型的角色——敵人和遊戲者。敵人將追逐遊戲者,玩家決定遊戲者往哪兒走。路上可能有障礙。兩種角色有一些共同的基本特徵,如力量、耐力、智力、敏捷和攻擊力。每一特徵都影響角色的防護(Protection)與攻擊(Power)能力。防護因子反應了角色防護攻擊的能力,而攻擊因子反映了攻擊對手的能力。特徵與防護或攻擊因子成正比或反比關係。
力量和耐力與防護和攻擊成正比例。擁有較高力量與耐力因子的角色,也多一些自我防護與反擊的機會。智力和敏捷與防護因子成正比例,而與攻擊成反比例。咱們假定是這樣的關係。
咱們定義一個ChasingGame的類,它有兩個方法,用以建立兩種類型的角色——遊戲者與敵人。CharacterBuilder基於前述矩陣所示各類特徵的關係構建角色。每一特徵因子影響被構建的角色的特性。顯示其靜態關係的類圖以下:
ChasingGame定義了createPlayer:builder和createEnemy:builder,經過CharacterBuilder的實例建立遊戲者和敵人角色。每一個方法有一套不一樣的特徵因子,用來定義角色的特性。StandardCharacterBuilder是具體的CharacterBuilder,它根據不一樣特徵因子實際構建角色。構建過程結束後,StandaraCharacterBuilder將返回Character的實例。Character的代碼以下:
#import <Foundation/Foundation.h> @interface Character : NSObject @property (nonatomic, assign) float protection; @property (nonatomic, assign) float power; @property (nonatomic, assign) float strength; @property (nonatomic, assign) float stamina; @property (nonatomic, assign) float intelligence; @property (nonatomic, assign) float agility; @property (nonatomic, assign) float aggressiveness; @end
Character定義全部類型角色共有的一套特徵,包括防護、攻擊、力量、耐力、智力、敏捷和攻擊力。Character的實現僅僅是定義了一個init方法和幾個屬性的同步,代碼以下:
#import "Character.h" @implementation Character - (id)init { if (self = [super init]) { _protection = 1.0; _power = 1.0; _strength = 1.0; _stamina = 1.0; _intelligence = 1.0; _agility = 1.0; _aggressiveness = 1.0; } return self; } @end
Character的實例不知道如何把本身構建成有意義的角色,因此才須要CharacterBuilder基於先前定義的特徵關係,構建有意義的角色。CharacterBuilder的代碼以下:
#import "StandarCharacterBuilder.h" @implementation StandarCharacterBuilder - (CharacterBuilder *)buildStrength:(float)value { // 更新角色的防護值 self.character.protection *= value; // 更新角色的攻擊值 self.character.power *= value; // 最後設定力量值並返回今生成器 return [super buildStrength:value]; } - (CharacterBuilder *)buildStamia:(float)value { // 更新角色的防護值 self.character.protection *= value; // 更新角色的攻擊值 self.character.power *= value; // 最後設定男離職並返回今生成器 return [super buildStamia:value]; } - (CharacterBuilder *)buildIntelligence:(float)value { // 更新角色的防護值 self.character.protection *= value; // 更新角色的攻擊值 self.character.power /= value; // 最後設定智力值並返回生成器 return [super buildIntelligence:value]; } - (CharacterBuilder *)buildAgility:(float)value { // 更新角色的防護值 self.character.protection *= value; // 更新角色的攻擊值 self.character.power /= value; // 最後設定敏捷值並返回今生成器 return [super buildAgility:value]; } - (CharacterBuilder *)buildAggressiveness:(float)value { // 更新角色的防護值 self.character.protection /= value; // 更新角色的攻擊值 self.character.power *= value; // 最後設定攻擊力值並返回今生成器 return [super buildAggressiveness:value]; } @end
接下來看看ChasingGame是如何使用StandardCharacterBuilder來構建各類角色的,代碼以下:
#import <Foundation/Foundation.h> #import "StandarCharacterBuilder.h" @interface ChasingGame : NSObject - (Character *)createPlayer:(CharacterBuilder *)builder; - (Character *)createEnemy:(CharacterBuilder *)builder; @end
#import "ChasingGame.h" @implementation ChasingGame - (Character *)createPlayer:(CharacterBuilder *)builder { [builder buildCharacter]; [builder buildStrength:50.0]; [builder buildStamia:25.0]; [builder buildIntelligence:75.0]; [builder buildAgility:65.0]; [builder buildAggressiveness:35.0]; return [builder character]; } - (Character *)createEnemy:(CharacterBuilder *)builder { [builder buildCharacter]; [builder buildStrength:80.0]; [builder buildStamia:65.0]; [builder buildIntelligence:35.0]; [builder buildAgility:25.0]; [builder buildAggressiveness:95.0]; return [builder character]; } @end
ChasingGame的實例在createPlayer:方法中構建了一個遊戲者角色,其特徵因子分別爲力量50.0、耐力25.0、智力75.0、敏捷65.0、攻擊力35.0.在createEnemy:方法中,也是相似的,只是使用了不一樣的特徵因子。咱們來看下在客戶單怎麼來使用,代碼以下:
#import "ViewController.h" #import "Character.h" #import "CharacterBuilder.h" #import "StandarCharacterBuilder.h" #import "ChasingGame.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 具體生成器 CharacterBuilder *characterBuilder = [[StandarCharacterBuilder alloc] init]; // 指導者 ChasingGame *chasingGame = [[ChasingGame alloc] init]; Character *player = [chasingGame createPlayer:characterBuilder]; Character *enemy = [chasingGame createEnemy:characterBuilder]; NSLog(@"player protection : %f aggressiveness : %f", player.protection, player.aggressiveness); NSLog(@"player protection : %f aggressiveness : %f", enemy.protection, enemy.aggressiveness); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
輸出信息以下:
2015-09-09 22:06:39.435 BuilderPatternDemo[3078:74535] player protection : 174107.140625 aggressiveness : 35.000000 2015-09-09 22:06:39.435 BuilderPatternDemo[3078:74535] player protection : 47894.738281 aggressiveness : 95.000000
生成器模式能幫助構建涉及部件與表現的各類組合對象,使用生成器模式就會帶來極大的便利性。