建造者模式(生成器模式)的浅出理解

如何让自己的文章变的高逼格?
就是随便写一写生活里的琐事
然后加上一句 : 爱情也是如此
那文章将化腐朽为神奇
比如 :
今早我明明设置了七点的闹钟, 可是一觉醒来已经是八点, 爱情也是如此....
我中午吃了一个包子, 我说要香菇馅, 阿姨却给我猪肉馅, 爱情也是如此...
设计模式学起来好枯燥, 可是还是让人贱嗖嗖的想学, 爱情也是如此....


对于建造者模式
看过书, 也看过博客
我对这个设计模式的总结为如下几句话 :
客户(Client)想要货
于是客户告诉了指导者(Director)我想要货
于是指导者指导建造者(Builder)去建造
客户不管指导者在哪里怎么搞到的货, 总之你要给我货
就像我去买包子
我告诉大妈我要买包子
大妈给我包子
我并不去问大妈怎么做的包子
流程大概就是这个样子 : Client - Director - Builder
UML图大概是这个样子 :


建造者模式(生成器模式)的浅出理解_第1张图片
UML 图

Builder是一个抽象接口, 声明了 buildPart 方法
buildPart 方法由 ConcreteBuilder 实现以构建产品 product
ConcreteBuilder 还有一个方法 getResult 方法, 用来返回产品实例
Director 定义了一个 create 方法
用来命令 Builder 的实例去创建产品
Director 和 Builder 形成一种聚合关系
Builder 是 Director 的组成部分
他们结合使整个模式运转

好了开始上代码
代码逻辑模仿我之前玩过的一款烧钱网游
省吃省喝就为买装备的烧钱网游
在网游中需要有很多角色
角色包括很多类型
有输出, 辅助, 封系
但是每种类型的角色都有共同的属性
有伤害, 防御, 速度和气血
只不过对于输出来说伤害高但是防御低
对于辅助来说伤害低但是防御高
当然你要是充钱多的话
什么都能高.....
然后角色类是这个样子 :

// HXCharacter.h
#import 

@interface HXCharacter : NSObject

/** 伤害值 */
@property (nonatomic, assign) CGFloat power;
/** 防御值 */
@property (nonatomic, assign) CGFloat protection;
/** 速度值 */
@property (nonatomic, assign) CGFloat velocity;
/** 气血值 */
@property (nonatomic, assign) CGFloat blood;
/** 角色类型 */
@property (nonatomic, copy) NSString *type;

//查看角色属性
- (void)lookLook;
@end

// HXCharacter.m
#import "HXCharacter.h"

@implementation HXCharacter

- (instancetype)init {
    if (self = [super init]) {
        //搞一搞初始值
        self.power = 1.0;
        self.protection = 1.0;
        self.velocity = 1.0;
        self.blood = 1.0;
    }
    return self;
}

- (void)lookLook {
    NSLog(@"\n  我是啥 : %@,   \n我的伤害 : %.2f,   \n我的防御 : %.2f,   \n我的速度 : %.2f,   \n我的气血 : %.2f,",self.type, self.power,self.protection,self.velocity,self.blood);
}

@end

他拥有很多属性和一个看一看方法(lookLook)
看一看方法可以输出这个角色的属性

然后来创建抽象 Builder 类:

// HXCharacterBuilder.h
#import 
#import "HXCharacter.h"

@interface HXCharacterBuilder : NSObject

@property (nonatomic, strong) HXCharacter *character;

/** 获取创建好的角色 */
- (HXCharacter *)getCharacter;

/** 增加伤害 */
- (instancetype)increasePower:(NSInteger)power;

/** 增加防御 */
- (instancetype)increaseProtection:(NSInteger)protection;

/** 增加速度 */
- (instancetype)increaseVelocity:(NSInteger)velocity;

/** 增加气血 */
- (instancetype)increaseBlood:(NSInteger)blood;

@end

// HXCharacterBuilder.m
#import "HXCharacterBuilder.h"

@implementation HXCharacterBuilder

- (instancetype)init {
    if (self = [super init]) {
        [self createCharacter];
    }
    return self;
}

- (void)createCharacter {
    self.character  = [[HXCharacter alloc] init];
}

/** 获取创建好的角色 */
- (HXCharacter *)getCharacter {
    return self.character;
}

/** 增加伤害 */
- (instancetype)increasePower:(NSInteger)power {
    self.character.power = power;
    return self;
}

/** 增加防御 */
- (instancetype)increaseProtection:(NSInteger)protection {
    self.character.protection = protection;
    return self;
}

/** 增加速度 */
- (instancetype)increaseVelocity:(NSInteger)velocity {
    self.character.velocity = velocity;
    return self;
}

/** 增加气血 */
- (instancetype)increaseBlood:(NSInteger)blood {
    self.character.blood = blood;
    return self;
}

@end

他实现了对角色属性的默认操作
还有一个 getCharacter 方法来返回创建好的角色

然后是继承 Builder 的 HXWarriorCharacterBuilder 类
HXWarriorCharacterBuilder 用来创建输出角色的建造者类

#import "HXCharacterBuilder.h"

@interface HXWarriorCharacterBuilder : HXCharacterBuilder

@end
#import "HXWarriorCharacterBuilder.h"

@implementation HXWarriorCharacterBuilder

/** 增加伤害 */
- (instancetype)increasePower:(NSInteger)power {
    self.character.power = power * 10;
    return self;
}

/** 增加防御 */
- (instancetype)increaseProtection:(NSInteger)protection {
    self.character.protection = protection * 5;
    return self;
}

/** 增加速度 */
- (instancetype)increaseVelocity:(NSInteger)velocity {
    self.character.velocity = velocity * 5;
    return self;
}

/** 增加气血 */
- (instancetype)increaseBlood:(NSInteger)blood {
    self.character.blood = blood * 5;
    return self;
}

- (void)createCharacter {
    self.character = [[HXCharacter alloc] init];
    self.character.type = @"我是战士, 我是一名输出";
}

@end

这个类实现了针对于输出角色属性的操作
创建角色过程中, 调用方法不同, 是对角色不同属性的创建
根据属性类型的不同, 属性值将乘以不同的成长比例
对于输出角色伤害的成长比例高, 而防御气血的成长比例稍微低一些
在实际应用这个模式的时候, 这里可能会有更复杂的对产品组件的创建代码

顺便搞一个用来创建辅助角色的建造者类

// HXDoctorCharacterBuilder.h
#import "HXCharacterBuilder.h"

@interface HXDoctorCharacterBuilder : HXCharacterBuilder

@end

// HXDoctorCharacterBuilder.m
#import "HXDoctorCharacterBuilder.h"

@implementation HXDoctorCharacterBuilder

/** 增加伤害 */
- (instancetype)increasePower:(NSInteger)power {
    self.character.power = power * 2;
    return self;
}

/** 增加防御 */
- (instancetype)increaseProtection:(NSInteger)protection {
    self.character.protection = protection * 10;
    return self;
}

/** 增加速度 */
- (instancetype)increaseVelocity:(NSInteger)velocity {
    self.character.velocity = velocity * 8;
    return self;
}

/** 增加气血 */
- (instancetype)increaseBlood:(NSInteger)blood {
    self.character.blood = blood * 10;
    return self;
}

- (void)createCharacter {
    self.character = [[HXCharacter alloc] init];
    self.character.type = @"我是医生, 我是一名辅助";
}

@end

同理于输出角色建造者类
对于辅助角色伤害的成长比例低, 而防御气血的成长比例稍微高一些

然后是指导者 Director 的类

// HXGameDirector.h
#import 
#import "HXCharacterBuilder.h"
#import "HXCharacter.h"

@interface HXGameDirector : NSObject
- (instancetype)initWithBuilder:(HXCharacterBuilder *)builder;

/** 创建辅助角色 */
- (void)createAuxiliaryCharacter;

/** 创建输出角色 */
- (void)createExportCharacter;
@end

// HXGameDirector.m
#import "HXGameDirector.h"

@interface HXGameDirector()
@property (nonatomic, strong) HXCharacterBuilder *builder;
@end

@implementation HXGameDirector
- (instancetype)initWithBuilder:(HXCharacterBuilder *)builder {
    if (self = [super init]) {
        self.builder = builder;
    }
    return self;
}

/** 创建辅助角色 */
- (void)createAuxiliaryCharacter {
    [self.builder increasePower:20];
    [self.builder increaseProtection:100];
    [self.builder increaseVelocity:80];
    [self.builder increaseBlood:100];
}

/** 创建输出角色 */
- (void)createExportCharacter {
     // 因为创建属性的方法, 返回了 builder 所以也可以这么调用
    [[[[self.builder increasePower:100]increaseProtection:50]increaseVelocity:100]increaseBlood:50];
}

@end

指导者有两个方法
分别是根据不同属性值创建输出角色和辅助角色
客户端将这么使用 :

- (void)viewDidLoad {
    [super viewDidLoad];

    //创建生成器
    HXCharacterBuilder *warriorBuilder = [[HXWarriorCharacterBuilder alloc] init];
    //根据生成器创建指导者
    HXGameDirector *warriorDirector = [[HXGameDirector alloc] initWithBuilder:warriorBuilder];
    //指导者利用生成器去生产
    [warriorDirector createExportCharacter];
    //在生成器中获取角色
    HXCharacter *warriorCharacter = [warriorBuilder getCharacter];
    //看看角色什么样
    [warriorCharacter lookLook];
    
    HXCharacterBuilder *doctorBuilder = [[HXDoctorCharacterBuilder alloc] init];
    HXGameDirector *doctorDirector = [[HXGameDirector alloc] initWithBuilder:doctorBuilder];
    [doctorDirector createAuxiliaryCharacter];
    HXCharacter *doctorCharacter = [doctorBuilder getCharacter];
    [doctorCharacter lookLook];
}

打印结果 :

HXBuilderPattern[17708:3030502] 
我是啥 : 我是战士, 我是一名输出,   
我的伤害 : 1000.00,   
我的防御 : 250.00,   
我的速度 : 500.00,   
我的气血 : 250.00,
HXBuilderPattern[17708:3030502] 
我是啥 : 我是医生, 我是一名辅助,   
我的伤害 : 40.00,   
我的防御 : 1000.00,   
我的速度 : 640.00,   
我的气血 : 1000.00,

到这里使用建造者模式把角色创建结束了
有一点需要说明 :
就是为什么要从 builder 中去获取最终产品
如果用 dirctor 直接返回产品的话, 客户就不需要知道 builder 了
这岂不是很方便?
但是这样的话, dirctor 就变成了工厂
dirctor 的 create 方法就变成了生产抽象产品的工厂方法
工厂设计模式看这里
而且 dirctor 将与所支持的产品绑定在一起
降低了模式的可复用性
对这里的理解, 我感觉还不是很到位, 希望有大神指点

最后区别一下建造者模式与抽象工厂的特点 :

建造者模式 :
构建复杂对象
以多个步骤构建对象
以多种方式构建对象
多步构建, 最后一步返回产品
专注一个特定产品的创建

抽象工厂 :
构建简单对象也可构建复杂对象
以单一步骤构建对象
以单一方式构建对象
立刻返回构建产品
强调一套产品
这里是代码

感谢阅读
你的支持是我写作的唯一动力


享元模式
工厂模式
中介者模式

你可能感兴趣的:(建造者模式(生成器模式)的浅出理解)