本文主要讨论一下iOS中的Builder Pattern。与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了。设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式,虽然这句话有点拗口!我希望我们都能宏观地看待某个设计模式,不必去太可以追求概念上的东西。事实上,只要你懂得如何应用,那此模式彼模式叫什么名称已经无所谓了。

我们先来看个例子,假设你现在要买一辆车,提出以下一堆要求:白色、价格10万以内、必须是国产车(爱国是必须的)、5座...,用iOS代码描述就是这样的:

         WZLCar *myCar = [[WZLCar alloc] init];
myCar.color = [UIColor whiteColor];
myCar.price = ;
myCar.family = @"China";
myCar.seatCount = ;
//...more properties

或者是这样:

 WZLCar *myCar = [WZLCar alloc] initWithColor:[UIColor whiteColor] price: family:@"China" seatCount: ....];

实际上,以上两种方式分别代表了两种iOS对象的初始化方式。在未使用Builder Pattern之前,这两种初始化对象方式都有不方便的地方。第一种方法灵活,但是如果你接触iOS时间长点就会发现,经常会记不住这个类到底有哪些property需要初始化,尤其是当这个类是被人提供给你的时候!我们多么希望类的提供者能搞点注释啊啥的告知我们一下。第二种方法则很清晰地告诉调用者到底有哪些property需要在创建对象时初始化。但是,当类的提供者有天跟你说:hey,哥们,现在业务逻辑改变了,我增加了一个xxx属性,init方法也变了。这时,你是不是很想打他?每新增一个新的属性,init方法就要变动,而且当需要初始化的属性多大十几二十个时,这个init方法要不要太壮观!

所以,当某个类的属性值很多时,我们可以考虑使用建造者模式Builder Pattern来让初始化过程清晰一些,类的使用者会很感恩你这么做的。用iOS描述大概是这样的:

 WZLCarBuilder *builder = [[WZLCarBuilder alloc] init];//builder里面列出了所有需要初始化的参数,可以认为是一个to-do list
builder.color=[UIColor whiteColor];
builder.price=;
builder.family=@"China";
builder.seatCount=;
WZLCar *car=[builder build];//build方法产生一个WZLCar实例

其中WZLCarBuilder类的property将WZLCar类中需要初始化的property复制了一遍。当你在实例化一个WZLCar对象而忘记那些参数时,可以跳转到WZLCarBuilder类的头文件看一下就一目了然了。从这种角度看,builder其实就是一个to-do list供类的调用者查阅。有强迫症的同学可以对以上代码并不感冒,因为它显得不够紧凑不够优雅,在初始化一个WZLCar对象前要搞一堆代码。有强迫症的coder大部分都是好程序员,那我们就尝试让它更优雅一些。我们可以这么做:

         WZLCar *myCar = [WZLCar creatWithBuilder:^(WZLCarBulider *builder){
builder.color = [UIColor whiteColor];
builder.price = ;
builder.family = @"China";
builder.seatCount = ;
}];
NSLog(@"myCar:%@", [myCar description]);

将builder的配置信息封装到block中,这样代码整体看起来紧凑很多,也给类的调用者很多提示信息。WZLCar的 + (WZLCar *)creatWithBuilder:(WZLCarBuliderBlock)block 方法实现如下,详见代码注释部分:

 + (WZLCar *)creatWithBuilder:(WZLCarBuliderBlock)block
{
NSParameterAssert(block != nil);//参数单元测试是必须的
WZLCarBulider *bulider = [[WZLCarBulider alloc] init];
block(bulider);//这里的builder是一个指针,block内部对其所作的改变都会被保留下来
return [bulider build];//build创建一个WZLCar实例
}

WZLCarBuliderBlock是一个block声明:

typedef void (^WZLCarBuliderBlock) (WZLCarBulider *bulder);

剩下的工作就是对WZLCarBuilder的build方法实现了:

 - (WZLCar *)build
{
NSAssert(self.color, @"color property is forcely to be initilized!");
WZLCar *car = [[WZLCar alloc] init];
car.color = self.color;
car.price = self.price;
car.family = self.family;
car.seatCount = self.seatCount;
return [car autorelease];
}

一些需要调用者强制初始化的参数可以build函数的开头处添加断言,一旦WZLCar类的调用者在初始化时没有初始化color就是断言失败抛出异常。这在多人协同开发时可以省事很多。下面我们像文章开头一般,调用一下WZLCar类:

 WZLCar *myCar = [WZLCar creatWithBuilder:^(WZLCarBulider *builder){
builder.color = [UIColor whiteColor];
builder.price = ;
builder.family = @"China";
builder.seatCount = ;
}];
NSLog(@"myCar:%@", [myCar description]);

Log确实打印出相应的信息,我就截图了,这就说明builder pattern确实让WZLCar的初始化产生效果。按照上面的代码,如果WZLCar类的使用者一时疏忽忘记初始化color属性,程序会在断言处抛异常:

WZLCar *myCar = [WZLCar creatWithBuilder:^(WZLCarBulider *builder){
//builder.color = [UIColor whiteColor];
builder.price = ;
builder.family = @"China";
builder.seatCount = ;
}];
NSLog(@"myCar:%@", [myCar description]);

===================================

在FaceBook的开源动画框架POP中也有对builder pattern类似的应用:

POPAnimatableProperty *animatableProperty = [POPAnimatableProperty propertyWithName:@"property" initializer:^(POPMutableAnimatableProperty *prop) {
prop.writeBlock = ^(id obj, const CGFloat values[]) {
};
prop.readBlock = ^(id obj, CGFloat values[]) {
};
}];

这里的initializer本质上就是builder,只是叫法不同而已。

PS:从本文的builder pattern实现中你也可以抽象出一些东西应用在其他方面,比如利用block来封装一些属性的配置信息,比如iOS8中新增加的UIAlertController类就用到这种思想,是用block让调用者在一个block内给出对UITextField的配置:

##THAT IS ALL.

=======================================

原创文章,转载请注明 编程小翁@博客园,邮件zilin_weng@163.com,微信Jilon,欢迎各位与我在C/C++/Objective-C/机器视觉等领域展开交流!

=======================================

【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数的更多相关文章

  1. iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...

  2. 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)

    原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...

  3. 【设计模式】建造者模式 Builder Pattern

    前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...

  4. 二十四种设计模式:建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 介绍将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 示例用同样的构建过程创建Sql和Xml的Insert()方法和Get()方 ...

  5. Python 设计模式之建造者模式 Builder Pattern

    #引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...

  6. 设计模式-05建造者模式(Builder Pattern)

    1.模式动机 比如我们要组装一台电脑,都知道电脑是由 CPU.主板.内存.硬盘.显卡.机箱.显示器.键盘和鼠标组成,其中非常重要的一点就是这些硬件都是可以灵活选择,但是组装步骤都是大同小异(可以组一个 ...

  7. 【UE4 设计模式】建造者模式 Builder Pattern

    概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...

  8. 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  9. 建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 它可以将多个简单的对象一步一步构建成一个复杂的对象. 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 主要解决:主要解决在软 ...

随机推荐

  1. Chrome开发者工具详解(4)-Profiles面板

    Chrome开发者工具详解(4)-Profiles面板 如果上篇中的Timeline面板所提供的信息不能满足你的要求,你可以使用Profiles面板,利用这个面板你可以追踪网页程序的内存泄漏问题,进一 ...

  2. 【转】ASP.NET"正在中止线程"错误原因

    最近做的系统中老出现的一些问题不太明白,在使用 Response.End.Response.Redirect 或 Server.Transfer 时出现 ThreadAbortException , ...

  3. MEF入门之不求甚解,但力求简单能讲明白(二)

    在上一篇文章中,我们已经学到了很基本的MEF概念和使用方法. 但我们导出的是一个object类型的实例,只能用来tostring,没有引用部件类库,也不能用里面的成员方法. 本篇,我们逐渐往简单的文件 ...

  4. Hello, Android多屏幕版

    Hello, Android Multiscreen Xamarin.Android 中处理导航 在这两部指南中,我们将扩展我们前面创建的Phoneword 应用,以处理第二个屏幕.本章主要介绍安卓的 ...

  5. LeetCode122:Best Time to Buy and Sell Stock II

    题目: Say you have an array for which the ith element is the price of a given stock on day i. Design a ...

  6. Guava学习笔记:Range

    在Guava中新增了一个新的类型Range,从名字就可以了解到,这个是和区间有关的数据结构.从Google官方文档可以得到定义:Range定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(C ...

  7. 1 UML基础

    学习设计模式的过程中,发现相关的作者们都会用UML类图来表示一个模式的整体脉络,这种方式确实直观明了,既能体现宏观思路.又能兼顾实现细节.真的是很妙的工具.在开始正式学习设计模式之前,有必要对UML有 ...

  8. SweetAlert – 替代 Alert 的漂亮的提示效果

    Sweet Alert 是一个替代传统的 JavaScript Alert 的漂亮提示效果.SweetAlert 自动居中对齐在页面中央,不管您使用的是台式电脑,手机或平板电脑看起来效果都很棒.另外提 ...

  9. Cool!15个创意的 CSS3 文本效果【下篇】

    这里文章收集了15个创意的 CSS3 文本效果,所有的都是精心挑选,这些可能会增加创意的火花到你的下一个项目.其中有些是用于特定用途,而另一些则适用于多种用途.如果你想要一个精彩而又充满色彩的文字效果 ...

  10. 【web前端面试题整理04】阿里一行之大神面对面

    前言 这段时间我在河南一家公司当了一段时间的前端主管,最后可耻的匿了,原因各种各样,最主要的就是不想呆在郑州了. 其实这里的同事还是很不错的,面对老总最后的挽留我不是没有动心,而是这个地方确实不太好, ...