选择建造本身的房子的人会把工程外包给承包商。单一承包商不能建造整个房子,他将其分解为几个部分,而后转包给几个实际的建筑商,他们懂得如何将零部件组装起来。房子由由风格、颜色和尺寸各不相同的部件组成。客户告诉承包商房子里都要有什么,而后承包商协调各房屋建筑商,决定须要作什么。应该如何建造,建筑商就如何施工。建房子是个复杂过程,单凭一双手就想建房子,即使可能也很是困难。若是承包商(指导者)与懂得如何建造的建筑商相互协调,这一过程简单得多且更易管理。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
生成器模式能帮助构建涉及部件与表现的各类组合对象,使用生成器模式就会带来极大的便利性。