概述
其核心思想是将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。
主要优缺点
在创建者模式中,客户端不再负责对象的创建与组装,而是把这个对象创建的责任交给其具体的创建者类,把组装的责任交给组装类,客户端只负责对象的调用,从而明确了各个类的职责。
虽然利用创建者模式可以创建出不同类型的产品,但是如果产品之间的差异巨大,则需要编写多个创建者类才能实现,如果这是结合工厂模式更好。
创建者模式主要由五个部分构成:组装类,抽象创建者类,实现抽象创建者类的具体创建者类,抽象产品和实现抽象产品的具体产品类。
UML图
时序图
代码示例:
创建构建者协议类Builder
#import <Foundation/Foundation.h>
// 构建者
@protocol Builder <NSObject>
// 构建部分
- (NSString *)builderPart;
@end
创建具体生成者类ConcreteBuild
ConcreteBuild.h
#import <Foundation/Foundation.h>
#import "Builder.h"
@interface ConcreteBuild : NSObject <Builder>
@end
ConcreteBuild.m
#import "ConcreteBuild.h"
@implementation ConcreteBuild
#pragma mark - Builder
- (NSString *)builderPart {
return @"实现协议, 返回产品";
}
@end
创建组装者类Director
Director.h
#import <Foundation/Foundation.h>
#import "Builder.h"
@interface Director : NSObject
// 创建传入的实现者
- (instancetype)initWithBuilder:(id<Builder>)builder;
// 建造
- (NSString *)construct;
@end
Director.m
#import "Director.h"
@interface Director ()
@property (nonatomic, copy) id<Builder> builder;
@end
@implementation Director
- (instancetype)initWithBuilder:(id<Builder>)builder {
self = [super init];
if (self) {
_builder = builder;
}
return self;
}
// 建造
- (NSString *)construct {
// 创建部件
return [self.builder builderPart];
}
@end
ViewController调用
#import "ViewController.h"
#import "Director.h"
#import "ConcreteBuild.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 1.创建生成者, 知道要做的产品
ConcreteBuild *build = [[ConcreteBuild alloc] init];
NSString *str2 = [build builderPart];
// 2.创建承包商
Director *director = [[Director alloc] initWithBuilder:build];
// 3.交付产品
NSString *str = [director construct];
NSLog(@"str = %@, str2 = %@",str, str2);
}
@end
使用构建者模式的需求:
客户要店主一台苹果电脑, 电脑有CPU 显卡 主板 系统
组装者(指导者): 店主(Director)
构建者: 苹果电脑
(协议) 生成者: CPU 显卡 主板 系统
UML图
Demo2
拓展生成者来处理最后的结构
首先创建协议类MacBuilder(生成者)
#import <Foundation/Foundation.h>
#import "MacComputerProtocol.h"
@protocol MacBuilder <NSObject>
// 构建CPU
- (id<MacBuilder>)buildCPU:(NSString *)cpu;
// 构建显卡
- (id<MacBuilder>)buildDisplay:(NSString *)display;
// 构建主板
- (id<MacBuilder>)buildMainboard:(NSString *)mainboard;
// 构建系统
- (id<MacBuilder>)buildOS:(NSString *)os;
// 构建
- (id<MacComputerProtocol>)build;
@end
创建协议MacComputerProtocol
#import <Foundation/Foundation.h>
@protocol MacComputerProtocol <NSObject>
// 处理器
- (void)cpu:(NSString *)cpu;
// 显卡
- (void)display:(NSString *)display;
// 主板
- (void)mainboard:(NSString *)mainboard;
// 系统
- (void)os;
@end
创建MacComputerBuilder类(构建者)
MacComputerBuilder.h
#import <Foundation/Foundation.h>
#import "MacBuilder.h"
@interface MacComputerBuilder : NSObject <MacBuilder>
@end
MacComputerBuilder.m
#import "MacComputerBuilder.h"
#import "MACComputer.h"
@interface MacComputerBuilder ()
@property (nonatomic, strong) id<MacComputerProtocol> computer;
@end
// 类似的调用方式, 就是典型的构建者调用模式
@implementation MacComputerBuilder
- (instancetype)init
{
self = [super init];
if (self) {
_computer = [[MACComputer alloc] init];
}
return self;
}
// 构建CPU
- (id<MacBuilder>)buildCPU:(NSString *)cpu {
[_computer cpu:cpu];
return self;
}
// 构建显卡
- (id<MacBuilder>)buildDisplay:(NSString *)display {
[_computer display:display];
return self;
}
// 构建主板
- (id<MacBuilder>)buildMainboard:(NSString *)mainboard {
[_computer mainboard:mainboard];
return self;
}
// 构建系统
- (id<MacBuilder>)buildOS:(NSString *)os {
[_computer os];
return self;
}
// 构建
- (id<MacComputerProtocol>)build {
NSLog(@"构建了一台苹果电脑");
//这种中间其实有很多逻辑需要处理,此次省略500行代码
return _computer;
}
@end
创建MACComputer类
MACComputer.h
#import <Foundation/Foundation.h>
#import "MacComputerProtocol.h"
@interface MACComputer : NSObject <MacComputerProtocol>
@end
MACComputer.m
#import "MACComputer.h"
@implementation MACComputer
// 处理器
- (void)cpu:(NSString *)cpu {
NSLog(@"Mac电脑处理器:%@",cpu);
}
// 显卡
- (void)display:(NSString *)display {
NSLog(@"Mac电脑显卡:%@",display);
}
// 主板
- (void)mainboard:(NSString *)mainboard {
NSLog(@"Mac电脑主板:%@",mainboard);
}
// 系统
- (void)os {
NSLog(@"MAC系统");
}
@end
创建组装者Director类
Director.h
#import <Foundation/Foundation.h>
#import "MacBuilder.h"
// 组装
@interface Director : NSObject
- (instancetype)initWithBuilder:(id<MacBuilder>)builder;
// 成品的方法
- (void)constructCPU:(NSString *)cpu display:(NSString *)display mainboard:(NSString *)mainboard;
@end
Director.m
#import "Director.h"
@interface Director ()
@property (nonatomic, strong) id<MacBuilder> builder;
@end
@implementation Director
- (instancetype)initWithBuilder:(id<MacBuilder>)builder {
self = [super init];
if (self) {
_builder = builder;
}
return self;
}
// 成品的方法
- (void)constructCPU:(NSString *)cpu display:(NSString *)display mainboard:(NSString *)mainboard {
[[[[_builder buildCPU:cpu] buildDisplay:display] buildMainboard:mainboard] build];
}
@end
ViewController调用
#import "ViewController.h"
#import "Director.h"
#import "MacComputerBuilder.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 第一种构建方式
// id<MacBuilder> build = [[MacComputerBuilder alloc] init];
// // 构建者
// Director *director = [[Director alloc] initWithBuilder:build];
// [director constructCPU:@"Intel i8" display:@"独立显卡" mainboard:@"超级主板"];
// 第二种方式
id<MacBuilder> build = [[MacComputerBuilder alloc] init];
// 构建者
id<MacComputerProtocol> com = [[[[build buildCPU:@"Intel i8"] buildDisplay:@"du li xian ka"] buildMainboard:@"zhu ban"] build];
NSLog(@"com = %@", com);
}
@end
实际开发中应用Demo
构建者模式变体
首先创建DrawBuilder类,再创建DrawView类
DrawView.h
#import <UIKit/UIKit.h>
@interface DrawView : UIView
@property (nonatomic, assign) CGFloat buildLabel;
@property (nonatomic, assign) CGFloat buildButton;
@property (nonatomic, assign) CGFloat buildSizeView;
@end
DrawView.m
#import "DrawView.h"
@implementation DrawView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame: frame];
if (self) {
self.backgroundColor = [UIColor grayColor];
}
return self;
}
// 使用drawRect,可以在控制器中设置值给view.
- (void)drawRect:(CGRect)rect {
[self setBackgroundColor:[UIColor redColor]];
// label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(self.buildLabel, 100, 50, 80)];
label.text = @"TZ";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor blackColor];
[self addSubview:label];
// 按钮
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, self.buildButton, 100, 50)];
[btn setTitle:@"蓝色" forState:UIControlStateNormal];
btn.titleLabel.backgroundColor = [UIColor redColor];
btn.titleLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:btn];
// 添加view
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 100, self.buildSizeView)];
subView.backgroundColor = [UIColor blueColor];
[self addSubview:subView];
UIImage *backgroundImage = [UIImage imageNamed:@"tupian"];
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
[self addSubview:backgroundView];
}
@end
DrawBuilder.h
#import <Foundation/Foundation.h>
#import "DrawView.h"
@interface DrawBuilder : NSObject
- (CGFloat)buildLabel; /**< 构建label */
- (CGFloat)buildButton; /**< 构建按钮 */
- (CGFloat)buildSizeView; /**< 构建蓝色的View */
- (DrawView *)loadView; /**< 构建结果 */
@end
DrawBuilder.m
#import "DrawBuilder.h"
@implementation DrawBuilder
- (CGFloat)buildLabel {
return 0;
}
- (CGFloat)buildButton {
return 0;
}
- (CGFloat)buildSizeView {
return 0;
}
- (DrawView *)loadView {
CGFloat drawWidth = 200;
CGFloat drawHeight = 300;
DrawView *drawView = [[DrawView alloc] initWithFrame:CGRectMake(0, 0, drawWidth, drawHeight)];
//
drawView.buildLabel = [self buildLabel];
drawView.buildButton = [self buildButton];
drawView.buildSizeView = [self buildSizeView];
return drawView;
}
@end
创建继承自DrawBuilder类的DrawSubBuilderOne和DrawSubBuilderTeo
DrawSubBuilderOne.m
#import "DrawSubBuilderOne.h"
@implementation DrawSubBuilderOne
- (CGFloat)buildLabel {
return 1;
}
- (CGFloat)buildButton {
return 1;
}
- (CGFloat)buildSizeView {
return 1;
}
@end
DrawSubBuilderTeo.m
#import "DrawSubBuilderTeo.h"
@implementation DrawSubBuilderTeo
- (CGFloat)buildLabel {
return 10;
}
- (CGFloat)buildButton {
return 150;
}
- (CGFloat)buildSizeView {
return 100;
}
@end
创建Director组装者
Director.h
#import <Foundation/Foundation.h>
#import "DrawBuilder.h"
@interface Director : NSObject
+ (DrawView *)creatView:(DrawBuilder *)builder;
@end
Director.m
#import "Director.h"
@implementation Director
+ (DrawView *)creatView:(DrawBuilder *)builder {
DrawView *drawView = [builder loadView];
return drawView;
}
@end
ViewController调用
#import "ViewController.h"
#import "DrawSubBuilderOne.h"
#import "DrawSubBuilderTeo.h"
#import "Director.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)btnClick:(id)sender {
// 创建者
// DrawBuilder *builder = [[DrawSubBuilderOne alloc] init];
DrawBuilder *builder = [[DrawSubBuilderTeo alloc] init];
// 组装
DrawView *drawView = [Director creatView:builder];
drawView.center = self.view.center;
[self.view addSubview:drawView];
}
@end