Builder Pattern 在 Objective-C 中的使用

在说 Builder Pattern 之前,我们先来看看一个场景。假设我们要预定一个 iPhone 6,要 64G 的,金色的,用代码表述大概是这样


1

2

3

4

// PFX 是一个前缀,因为直接写 iPhone6 不符合类名大写的习惯,写成 IPhone6 更是怪异 ╮(╯▽╰)╭

PFXiPhone6 *iphone = [[PFXiPhone6 alloc] init];

iphone.storage = 64;

iphone.color = [UIColor goldenColor];

也可以是另一种方式


1

PFXiPhone6 *iPhone = [[PFXiPhone6 alloc] initWithStorage:64 color:[UIColor goldenColor]];

第一种方式可扩展性好些,但无法约束必须设置某些 property。第二种方式修正了这个问题,但扩展性也差了。

假如又有了新需求,要让客户可以选择发售区域,比如港行,国行,美版等等。对于第一种,自然可以新增一个属性,但使用者很可能完全不知道新增了这么个属性。对于第二种,则只能再新建一个初始化方式,如 -[initWithStorage:color:place]。那如果又有新的需求,比如选择是否刻字,以及刻哪些字呢?或者可以选择外壳的种类等等。这两种方式都不能很好地处理需求的变更。

现在我们来说说 Builder Pattern,这个模式可以在各种语言里被很方便地实现,比如 javascript


1

2

3

4

5

new PFXiPhone6Builder()

  .setStorage(64)

  .setColor(‘golden‘)

  .setPlace(‘HK‘)

  .build();

当有新的属性时,再加一个 setProperty 即可。如果漏写了某个属性,可以在 build 里检查。

在 Objective-C 里,这样的链式写法不是很流行(Masonry里这种写法用的比较多),所以,在 OC 里写起来大概会是这样


1

2

3

4

5

PFXiPhone6Builder *builder = [[PFXiPhone6Builder alloc] init];

builder.storage = 64;

builder.color = [UIColor goldenColor];

builder.place = @"HK";

PFXiPhone6 *iphone = [builder build];

如果少了什么属性,在 build 时检查下即可。这样既解决了不方便扩展的问题,当有新的属性时也可以知道。

不过看起来还是不够优雅,这个 builder 只是一个临时工具,用完了就扔掉了,既然这样,那有没有可能写法上符合 OC 的传统,又让这个 builder 「临时出现」一下?且看下面这段代码


1

2

3

4

5

PFXiPhone6 *iPhone6 = [PFXiPhone6 createWithBuilder:^(PFXiPhone6Builder *builder){

    builder.storage = 64;

    builder.color = [UIColor goldenColor];

    builder.place = @"HK";

}];

是不是看起来舒服多了。builder 只是在 block 范围内起作用,不会影响当前 context 的变量。这个 +[createWithBuilder:] 的代码如下


1

2

3

4

5

6

+ (instancetype)createWithBuilder:(BuilderBlock)block {

    NSParameterAssert(block);

    PFXiPhone6Builder *builder = [[PFXiPhone6Builder alloc] init];

    block(builder);

    return [builder build];

}

这里 build 方法,也有两种实现,第一种


1

2

3

4

5

6

7

8

9

10

11

12

13

14

// PFXiPhone6Builder

- (PFXiPhone6 *)build

{

    return [[PFXiPhone6 alloc] initwithBuilder:self];

}

// PFXiPhone6

- (instancetype)initwithBuilder:(PFXiPhone6Builder *)builder

{

    if (self = [super init]) {

        _storage = builder.storage;

        _color = builder.color;

        _place = builder.place;

    }

}

另外一种是把两个过程合并为一个过程


1

2

3

4

5

6

7

8

9

10

11

// PFXiPhone6Builder

- (PFXiPhone6 *)build

{

    // 可以在这里对 property 做检查

    NSAssert(self.place, @"发行区别忘了填哦");

    PFXiPhone6 *iphone6 = [[PFXiPhone6 alloc] init];

    iPhone6.storage = self.storage;

    iPhone6.color = self.color;

    iPhone6.place = self.place;

    return iPhone6;

}

这两种方式的区别在于对参数的处理,前一个是在目标 Class 中处理,后一种是在 Builder 中处理。

在 Facebook 的 pop 中也有类似的使用,如


1

2

3

4

5

6

POPAnimatableProperty *animatableProperty = [POPAnimatableProperty propertyWithName:@"property" initializer:^(POPMutableAnimatableProperty *prop) {

    prop.writeBlock = ^(id obj, const CGFloat values[]) {

    };

    prop.readBlock = ^(id obj, CGFloat values[]) {

    };

}];

这里的 initializer 其实就是 builder

我在写蘑菇街的基础框架时,也有用到过几处,觉得还是蛮方便的,尤其对使用者来说。比如这个可以横向或纵向滚动的包含可点击 Items 的 collectionView。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

self.collectionView = [MGJFlowCollectionView collectionViewWithBuilder:^(MGJFlowCollectionViewBuilder *builder) {

    builder.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    builder.minimumInteritemSpacing = 10;

    builder.minimumLineSpacing = 10;

    builder.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);

    CGSize itemSize = CGSizeMake(81, 100);

    builder.itemSize = itemSize;

    builder.dataSource = @[@1,@2,@3,@4,@5,@6, @7,@8, @9, @10];

    builder.cellBuilder = ^UIView *(NSNumber *number){

        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemSize.width, itemSize.height)];

        view.backgroundColor = [UIColor mgj_random];

        return view;

    };

}];

这样就能通过简单的配置来生成一个水平的或垂直的 collectionView 了。

使用 Builder Pattern 还有一个好处,就是可以将零散的配置统一起来。比如要创建一个 CollectionView,我们需要设置 layout,还要设置 layout 的一些属性,还要设置 DataSource / Delegate 等,现在可以在一个地方统一设置,可读性上也会好一些。

所以如果遇到需要多个参数,甚至某个参数自己还包含了各种参数时,可以考虑下 Builder Pattern。

时间: 2024-10-10 21:08:32

Builder Pattern 在 Objective-C 中的使用的相关文章

C#设计模式之四建造者模式(Builder Pattern)【创建型】

原文:C#设计模式之四建造者模式(Builder Pattern)[创建型] 一.引言 今天我们要讲讲Builder模式,也就是建造者模式,当然也有叫生成器模式的,英文名称是Builder Pattern.在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:电脑,它就是一个复杂的物品,它主要是由CPU.主板.硬盘.显卡.机箱等组装而成的.手机当然也是复杂物品,由主板,各种芯片,RAM 和ROM  摄像头之类的东西组成.但是无论是电脑还是手机,他们的组装过程是固定的,就拿手机来说,组装流水线

建造者模式(Builder Pattern)

一. 建造者(Builder)模式 建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.在软件系统中,有时候面临一个复杂对象的创建工作,该对象通常由各个部分子对象用一定的算法构成,或者按一定的步骤组合而成:这些算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求的变化而不断变化. 二.建造者模式的结构 建造者模式参与者: ◊ Builder:为创建一个Product对象的各个部件指定抽象接口: ◊ ConcreteBuilder ° 实现Builde

生成器模式(Builder Pattern)

一. 建造者(Builder)模式 建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象. 对象性质的建造 有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用.比如,一个电子邮件有发件人地址.收件人地址.主题.内容.附录等部分,而在最起码的收件人地址未被赋值之前,这个电子邮件不能发出. 有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义.在某个性质没有赋值之前,另一个性质则无法赋值.

.NET设计模式 第二部分 创建型模式(3)—建造者模式(Builder Pattern)

建造者模式(Builder Pattern) ——.NET设计模式系列之四 Terrylee,2005年12月17日 概述 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定.如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式. 本文通过现实生活中的买

Builder Pattern

遇到多个构造器形参时要考虑用构建器 引言 遇到多个构造器时要考虑用构建器(builder) 重叠构造器(telescoping constructor) // Telescoping constructor pattern - does not scale well! - Pages 11-12 /** * 营养成分表 */ public class NutritionFacts { private final int servingSize; // (mL) required private

第4章 建造者模式(Builder Pattern)

原文 第4章 建造者模式(Builder Pattern) 定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 实用范围 1 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 2 当构造过程必须允许被构造的对象有不同表示时. 角色 在这样的设计模式中,有以下几个角色: 1 builder:为创建一个产品对象的各个部件指定抽象接口. 2 ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部

深入浅出设计模式——建造者模式(Builder Pattern)

模式动机无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮.方向盘.发送机等各种部件.而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象.用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节. 在软件开发中,也存在大量类似汽车一样的复杂对象,它们拥有一系列成员属性,这些成员

"围观"设计模式(9)--创建型之创建者模式(Builder Pattern)

生成器模式(英:Builder Pattern)是一种设计模式,又名:建造模式,是一种对象构建模式.它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象.----WIKIPEDIA 个人的理解: 建造者模式可以设置不同的属性或者行为,创建出不一样的对象.比如说生产汽车,假如有三个重要的工序,塑形.拼装.上色.那么可以通过创建者模式来设置,这三道工序中不同的车来说,三道工序可能就是不一样的.通过创建者模式来创建出对象的表现形式也自然就不一样.

建造者模式(Builder Pattern)

模式定义 造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. UML类图 Builder:抽象建造者 ConcreteBuilder:具体建造者 Director:指挥者 Product:产品角色 代码结构 public static class BuilderApp { public static void Run() { Director director = new Director(); Builder b1 = new