设计模式之(五)生成器模式(建造模式)

本文首发于个人博客.html)

前言

什么是生成器模式

生成器模式 又名:建造模式 属于创建型模式,在wikipedia中的定义如下

生成器模式(英:Builder Pattern)是一种设计模式,又名:建造模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

适用性

在以下情况使用生成器模式:

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;
  • 当构造过程必须允许被构造的对象有不同的表示时。

参与者

  • Builder 抽象建造者类
    • 为创建一个Product对象的各个部件指定抽象接口。
  • ConcreteBuilder 建造者类
    • 实现Builder的接口以构造和装配该产品的各个部件。
    • 定义并明确它所创建的表示。
    • 提供一个检索产品的接口
  • Director 导演类
    • 构造一个使用Builder接口的对象。
  • Product 产品类
    • 表示被构造的复杂对象。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。
    • 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

代码

YZBuilderCar

创建YZBuilderCar类,有两个属性,分别是名字和价格

1
2
3
4
5
6
7
8
9
#import <Foundation/Foundation.h>


@interface YZBuilderCar : NSObject
@property (nonatomic, strong)NSString *name;// 名字
@property (nonatomic, strong)NSString *price;// 价格

-(YZBuilderCar *)makeCar;
@end

实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import "YZBuilderCar.h"

@interface YZBuilderCar()
@end


@implementation YZBuilderCar

- (NSString *)description{
return [NSString stringWithFormat:@"我是一辆:%@ 车 价格:%@",self.name,self.price];
}

- (YZProductCar *)makeCar{
YZBuilderCar *car = [[YZBuilderCar alloc] init];
car.name = self.name;
car.price = self.price;
return car;
}

@end

YZBMWCarYZAudiCar继承自YZBuilderCar

创建车型YZBMWCar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import "YZProductCar.h"


@interface YZBMWCar : YZBuilderCar

@end



#import "YZBMWCar.h"

@implementation YZBMWCar
- (instancetype)init
{
self = [super init];
if (self) {
self.name = @"宝马740Li";
self.price = @"98万";
}
return self;
}

@end

创建车型YZAudiCar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#import "YZProductCar.h"


@interface YZAudiCar : YZBuilderCar

@end


#import "YZAudiCar.h"

@implementation YZAudiCar
- (instancetype)init
{
self = [super init];
if (self) {
self.name = @"奥迪Q5";
self.price = @"45万";
}
return self;
}

@end

YZDirector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <Foundation/Foundation.h>

#import "YZBuilderCar.h"

@interface YZDirector : NSObject
// 建造一辆车
+ (YZProductCar *)creatBuickCar:(YZBuilderCar *)builder;
@end


#import "YZDirector.h"

@implementation YZDirector
+ (YZProductCar *)creatBuickCar:(YZBuilderCar *)builder{
YZProductCar *car = [builder makeCar];
return car;
}
@end

使用

1
2
3
4
5
6
7
8
9
10
int main(int argc, const char * argv[]) {
@autoreleasepool {

YZBuilderCar *car = [[YZBMWCar alloc] init];
YZDirector *dir = [YZDirector creatBuickCar:car];
NSLog(@"%@",dir.description);

}
return 0;
}

输出为

我是一辆:宝马740Li 车 价格:98万

建造者模式的优点

首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在Director类中对整体而言可以取得比较好的稳定性。

其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的ConcreteBuilder类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。

建造者模式与工厂模式的区别

我们可以看到,建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个”导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。

总结

建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。

Demo地址