iOS设计模式之生成器

2020/6/27 23:56:34

本文主要是介绍iOS设计模式之生成器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

定义

生成器模式:将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。

其整体思想是分离“什么”与“如何”。将复杂对象的构建过程分解为客户-指导者-生成器(client-director-builder)的关系。这样将更容易管理和复用整个过程。

使用场景

在以下情形时,自然会想到使用这一模式:

  • 需要创建设计各种部件的复杂对象。创建对象的算法应该独立于部件的装配方式。常见于构建组合对象。
  • 构建过程需要以不同的方式(例如,部件或表现的不同组合)构建对象

类图结构

生成器有三个角色,指导者Director,生成器Builder,产品Product,其三者的关系如下图所示

Director持有builder对象,构成聚合关系,用于构建产品Product。Director的construct方法实现为使用持有的builder执行buildPart方法。Builder是一个抽象接口,声明了一个buildPart方法。ConcreteBuilder实现继承的buildPart与getProduct方法,buildPart实现调用buildPartA,buildPartB,buildPartC方法来构建Product的不同细节。最后使用getProduct返回已经构建好的产品对象。

生成器与抽象工厂的对比

抽象工厂与生成器模式在抽象对象创建方面有许多相似之处。然而,两者却有着不同的设计理念。

  1. 生成器关注的是分布创建复杂对象,很多时候同一类型的对象可以以不同的方式创建。
  2. 抽象工厂的重点在于创建简单或者复杂产品的套件。
  3. 生成器在多步创建过程的最后一步返回产品,而抽象工厂则立即返回产品。

两者差异如下表:

生成器 抽象工厂
构建复杂对象 构建简单或者复杂对象
以多步骤构建对象 以单一步骤构建对象
以多种方式构建对象 以单一方式构建对象
在构建过程的最后一步返回产品 立刻返回产品
专注一个特定的产品 强调一套产品

简单的说,生成器更注重过程的拆分,抽象工厂更注重结果的产生。

代码实现

下面将以构建游戏中的角色为例,使用生成器模式。

需求如下:我们需要构建两个游戏人物,敌人(Enemy)与游戏者(Player)。两种角色都有一些基本的基本特征,如力量(strength),耐力(stamina),智力(intelligence),敏捷(agility)和攻击力(aggressiveness)。每一个特征会影响角色的防御(Protection)和攻击(Power)能力。每项特征与人物的攻击或者防御的正反比关系如下:

防御 攻击
力量(strength)
耐力(stamina)
智力(intelligence)
敏捷(agility)
攻击力(aggressiveness)

根据上述需求,设计出如下静态类图

XQChasingGame定义了createPlayer:builder与createEnemy:builder来创建游戏者与敌人。每个方法有一套不同的特殊因子,用来定义角色的特性。XQStandardCharacterBuilder是XQCharacterBuilder的一个子类,根据不同的特征因子创建实际的角色。构建完成后,XQStandardCharacterBuilder返回XQCharacter的实例。

  1. 构建角色对象XQCharacter
@interface XQCharacter : NSObject

@property (nonatomic, assign) float protection;
![](https://user-gold-cdn.xitu.io/2020/6/24/172e213819f3556e?w=1435&h=697&f=png&s=118117)
@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

@implementation XQCharacter

- (instancetype)init{
  if (self = [super init]){
      self.protection = 1.0;
      self.power = 1.0;
      self.strength = 1.0;
      self.stamina = 1.0;
      self.intelligence = 1.0;
      self.agility = 1.0;
      self.aggressiveness = 1.0;
  }
  return self;
}

@end
复制代码

在初始化方法init中,给每个属性默认赋值1.0。

  1. 构建抽象类XQCharacterBuilder
@interface XQCharacterBuilder : NSObject

@property (nonatomic, strong, readonly) XQCharacter *character;

- (XQCharacterBuilder *)createCharacter;
- (XQCharacterBuilder *)buildStrength:(float)value;
- (XQCharacterBuilder *)buildStamina:(float)value;
- (XQCharacterBuilder *)buildIntelligence:(float)value;
- (XQCharacterBuilder *)buildAgility:(float)value;
- (XQCharacterBuilder *)buildAggressiveness:(float)value;

@end

@interface XQCharacterBuilder ()

@property (nonatomic, strong, readwrite) XQCharacter *character;

@end

@implementation XQCharacterBuilder

- (XQCharacterBuilder *)createCharacter{
    self.character = [[XQCharacter alloc] init];
    return self;
}

- (XQCharacterBuilder *)buildStrength:(float)value{
    self.character.strength = value;
    return self;
}

- (XQCharacterBuilder *)buildStamina:(float)value{
    self.character.stamina = value;
    return self;
}

- (XQCharacterBuilder *)buildIntelligence:(float)value{
    self.character.intelligence = value;
    return self;
}

- (XQCharacterBuilder *)buildAgility:(float)value{
    self.character.agility = value;
    return self;
}

- (XQCharacterBuilder *)buildAggressiveness:(float)value{
    self.character.aggressiveness = value;
    return self;
}

@end
复制代码

XQCharacterBuilder中声明对应的对象创建与属性赋值接口,定义了默认的赋值行为,将对应的属性值赋给创建的对象character。

3.构建具体子类XQStandardCharacterBuilder

@interface XQStandardCharacterBuilder : XQCharacterBuilder

- (XQCharacterBuilder *)buildStrength:(float)value;
- (XQCharacterBuilder *)buildStamina:(float)value;
- (XQCharacterBuilder *)buildIntelligence:(float)value;
- (XQCharacterBuilder *)buildAgility:(float)value;
- (XQCharacterBuilder *)buildAggressiveness:(float)value;

@end

@implementation XQStandardCharacterBuilder

- (XQCharacterBuilder *)buildStrength:(float)value{
    self.character.protection *= value;
    self.character.power *= value;
    return [super buildStrength:value];
}

- (XQCharacterBuilder *)buildStamina:(float)value{
    self.character.protection *= value;
    self.character.power *= value;
    return [super buildStamina:value];
}

- (XQCharacterBuilder *)buildIntelligence:(float)value{
    self.character.protection *= value;
    self.character.power /= value;
    return [super buildIntelligence:value];
}

- (XQCharacterBuilder *)buildAgility:(float)value{
    self.character.protection *= value;
    self.character.power /= value;
    return [super buildAgility:value];
}

- (XQCharacterBuilder *)buildAggressiveness:(float)value{
    self.character.protection /= value;
    self.character.power *= value;
    return [super buildAggressiveness:value];
}

@end
复制代码

在XQStandardCharacterBuilder类声明中,重新声明重载父类的方法,以明确该类的任务与职责。

在XQStandardCharacterBuilder类实现中,针对每个基础属性对角色的防御和攻击的影响赋值。按照矩阵中的比例关系定义,影响角色的攻击和防御值。最后再调用父类的对应方法给属性赋值,并且返回自身。(返回自身self的好处我们下面会说到)

  1. 构建指导者XQChasingGame
@interface XQChasingGame : NSObject

- (XQCharacter *)createPlayer:(XQCharacterBuilder *)builder;

- (XQCharacter *)createEnemy:(XQCharacterBuilder *)builder;

@end

@implementation XQChasingGame

- (XQCharacter *)createPlayer:(XQCharacterBuilder *)builder{
    [[[[[[builder createCharacter]
         buildStrength:50.f]
        buildStamina:25.f]
       buildIntelligence:75.f]
      buildAgility:65.f]
     buildAggressiveness:35.f];
    return builder.character;
}

- (XQCharacter *)createEnemy:(XQCharacterBuilder *)builder{
    [[[[[[builder createCharacter]
         buildStrength:80.f]
        buildStamina:65.f]
       buildIntelligence:35.f]
      buildAgility:25.f]
     buildAggressiveness:95.f];
    return builder.character;
}

@end
复制代码

XQChasingGame声明了创建游戏者与敌人的方法,内部实现根据需求要求角色属性不同传递不同的属性值。由于在具体子类XQStandardCharacterBuilder中,属性赋值方法都返回自身,这里就可以连续调用,构成单一语句。最后,将构建好的角色返回给外部使用。

  1. 客户端调用
XQStandardCharacterBuilder *builder = [XQStandardCharacterBuilder new];
XQChasingGame *game = [XQChasingGame new];
XQCharacter *player = [game createPlayer:builder];
XQCharacter *enemy = [game createEnemy:builder];
复制代码

客户端生成XQStandardCharacterBuilder与XQChasingGame的实例,调用实例方法createPlayer与createEnemy创建游戏者与敌人角色。然后就可以使用两个角色对象投入游戏中。

总结

生成器模式能帮助构建涉及部件与表现的各种组合的对象。防止指导者Director成为一个庞大的类。将角色构建算法放在一个具体的XQCharacterBuilder中。



这篇关于iOS设计模式之生成器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程