第一板斧
何为生成器模式?
生成器模式(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];
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。