资讯专栏INFORMATION COLUMN

设计模式三板斧之--生成器

mumumu / 709人阅读

摘要:针对此类关系的设计模式称为生成器。根据中文翻译的不同,建造者模式又可以称为生成器模式。和形成一种聚合关系产品角色类图时序图第三板斧生成器与抽象工厂的对比两者有相似之处。

第一板斧 何为生成器模式?
生成器模式(Builder): 将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。
what?说啥呢?
举个例子: 选择建造自己的房子的人会把工程外包给承包商。单一承包商不能建造整个房子,他将其分解为几个部分,然后转包给几个实际的建筑商,他们懂得如何将零部件组装起来。房子由由风格、颜色和尺寸各不相同的部件组成。客户告诉承包商房子里都要有什么,然后承包商协调各房屋建筑商,决定需要做什么。应该如何建造,建筑商就如何施工。建房子是个复杂过程,单凭一双手就想建房子,即便可能也非常困难。如果承包商(指导者)与懂得如何建造的建筑商相互协调,这一过程简单得多且更易管理。
解决什么问题

有时,构建某些对象有多种不同方式。如果这些逻辑包含在构建这些对象的类的单一方法中,构建的逻辑就会变得非常复杂(比如,针对各种构建需求的一大片嵌套if-else或者switch-case语句)。如果能够把构建过程分解为客户——指导者——生成器的关系,那么过程将更容易管理与复用。针对此类关系的设计模式称为生成器。

建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。

如果我们用了生成器模式,那么用户就只需指定需要建造的类型就可以到带到它们,而建造的过程和细节就不需知道了。

第二板斧 生成器结构

建造者模式包含如下角色:

Builder:抽象建造者

Builder是一个抽象接口,声明了一个buildPart方法,该builder方法由ConcreteBuilder实现,以构造实际产品(Product).

ConcreteBuilder:具体建造者

Director:指挥者

Director定义了一个construct方法,命令Builder的实例去buildPart。Director和Builder形成一种聚合关系.

Product:产品角色

类图

时序图

第三板斧 生成器与抽象工厂的对比

两者有相似之处。但是,一方面生成器关注的是分步创建复杂对象,很多时候同一类型的对象可以以不同的方式创建。另一方面,抽象工厂的重点在于创建简单或复杂产品的套件,生成器在多步创建过程的最后一步返回产品,而抽象工厂会立即返回产品

生成器 抽象工厂
构建复杂对象 构件简单或复杂对象
以多个步骤构建对象 以单一步骤构建对象
以多种方式构建对象 以单一方式构建对象
在构建过程的最后一步返回产品 立刻返回产品
专注一个特定产品 强调一套产品
代码演示
现在以生产车的例子作演示,这里的三个角色分别是:

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];
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/16525.html

相关文章

  • Linux环境基础开发工具使用

    摘要:环境基础开发工具使用软件包管理器的三板斧查看软件包安装软件卸载软件和互传文件的三种模式的转换命令模式插入模式底行模式编译器使用函数库调试器使用项目自动化构建工具软件包管理器软件包和软件包管理器就好比手机上的和应用 ...

    Dean 评论0 收藏0
  • 一看就懂的JS抽象语法树

    摘要:前言是现在几乎每个项目中必备的一个东西,但是其工作原理避不开对的解析在生成的过程,有引擎,早期了项目,了解这个之前我们先来看看这种引擎解析出来是什么东西。 前言 babel是现在几乎每个项目中必备的一个东西,但是其工作原理避不开对js的解析在生成的过程,babel有引擎babylon,早期fork了项目acron,了解这个之前我们先来看看这种引擎解析出来是什么东西。不光是babel还有...

    HackerShell 评论0 收藏0
  • 【Linux】linux环境基础开发工具使用

    摘要:函数名列出某个函数的源代码,含函数名上下各五行类比调试或从开始连续而非单步执行程序遇到断点停下。相当于中的或单条执行。 目录 一、调试器gdb 1、可以使用gdb的可执行文件生成 2、使用命令 1、开始调试和退出调试 2、list 3、类比vs调试 4、代码调试三剑客 5、变量 6、断点 二...

    dongfangyiyu 评论0 收藏0
  • 后端知识- 收藏集 - 掘金

    摘要:常见的八大排序算法,他们之间关系如下被人忽视的面向对象的六大原则后端掘金前言作为文集的第一篇,我觉得有必要介绍一下大概的写作规划。 Java多线程干货系列—(四)volatile关键字| 掘金技术征文 - 掘金原本地址:Java多线程干货系列—(四)volatile关键字博客地址:http://tengj.top/ 前言 今天介绍下volatile关键字,volatile这个关键字可能...

    Youngdze 评论0 收藏0
  • 后端知识- 收藏集 - 掘金

    摘要:常见的八大排序算法,他们之间关系如下被人忽视的面向对象的六大原则后端掘金前言作为文集的第一篇,我觉得有必要介绍一下大概的写作规划。 Java多线程干货系列—(四)volatile关键字| 掘金技术征文 - 掘金原本地址:Java多线程干货系列—(四)volatile关键字博客地址:http://tengj.top/ 前言 今天介绍下volatile关键字,volatile这个关键字可能...

    scola666 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<