iOS架构师_构建者模式

概述

其核心思想是将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。

主要优缺点

在创建者模式中,客户端不再负责对象的创建与组装,而是把这个对象创建的责任交给其具体的创建者类,把组装的责任交给组装类,客户端只负责对象的调用,从而明确了各个类的职责。
虽然利用创建者模式可以创建出不同类型的产品,但是如果产品之间的差异巨大,则需要编写多个创建者类才能实现,如果这是结合工厂模式更好。

创建者模式主要由五个部分构成:组装类,抽象创建者类,实现抽象创建者类的具体创建者类,抽象产品和实现抽象产品的具体产品类。

这里写图片描述

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

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值