IOS设计架构模式:构建者模式和中介者模式

一、构建者模式

       什么是构建者模式?

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

       比如,建造一栋大厦,那么就需要一个总建筑工程师(也就是指导者,相当于uml图中的组装者),N个包工头(也就是承包商,相当于uml图中的构建者),一个包工头有M个小工(也就是搬砖的、贴砖的、木工等等,相当于uml图中的生成者),指导者可以使用承包商A、承包商B、承包商C的自由组合,单个承包商又可以使用搬砖的、贴砖的、木工的自由组合,这样就把构建和组装分离开了。

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

        代码示例:

创建构建者协议类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

        实际开发Demo

        生成者(工人)先实现DrawView,好比一开始生成具体小产品,构建者(包工头)再把这些小产品构建成具体大产品DrawBuilder,指导者Director(建筑总工程师)依据自己的需求去选择DrawSubBuilderOne(具体包工头)或者DrawSubBuilderTeo(具体包工头)进行组装。

先创建生成者

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.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.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.m

#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

运行结果:

二、中介者模式

何为中介者模式?

       中介者模式是用一个对象来封装一组或者一系列对象的交互方式,使对象间的交互可以在一个中介者对象中处理,从而使各对象耦合松散,而且可以独立的改变它们之间的交互。中介者就好比站在十字路口的交通警察,如果改变十字路口的交通模式,只需要把新的交通策略给交通警察即可,而不是路上的所有车辆,这样才能更好的协调来自不同方向车辆。

中介者模式有什么用?

       说到中介者模式的作用,其实从上述的定义中便可以知道其大体用处,无非是用来集中的管理一组对象的交互,从而降低各个对象间的耦合度。当一组对象彼此间的依赖程度较高,导致难以复用时,便可以采用该模式。大家对中介这种角色估计也不陌生,所以今天的设计模式就以这个房地产中介作为故事背景吧!

1.png

        从无中介.jpg可以看出,要是没有中介的存在,买卖家之间的交流是如此困难且复杂。买家买房要跑去找卖家,卖家买房又得跑去找买家。如果现实真的如此,估计买卖家早就拍桌子说:“老子xx不买(卖)了!”如此反复,房地产业还可能像现在这样撑起国家经济吗?

2.png

好了,有中介的接入,一切都变得so easy了!买家要买房,直接到中介看房源,卖家卖房,直接委托中介推销,买卖家通过中介相互取得联系,进行沟通,最后达成买卖共识。呃..不瞎扯了,直接写个demo就清楚了!!!!

如图,同事间通过中介者进行交互,中介者和同事都是抽象类,首先先创建这2个抽象类AbstrctColleague和AbstractMediator。

AbstrctColleague.h

#import <Foundation/Foundation.h>
@class AbstrctColleague;

@protocol ColleagueDelegate <NSObject>

// 跟colleague对象的交互
- (void)colleagueEvent:(AbstrctColleague *)event;

@end

@interface AbstrctColleague : NSObject
@property (nonatomic, weak) id<ColleagueDelegate> delegate;
@end

AbstrctColleague.m

#import "AbstrctColleague.h"

@implementation AbstrctColleague

@end

AbstractMediator.h

#import <Foundation/Foundation.h>
#import "AbstrctColleague.h"

@interface AbstractMediator : NSObject <ColleagueDelegate>

@end

AbstractMediator.m

#import "AbstractMediator.h"

@implementation AbstractMediator

- (void)colleagueEvent:(AbstrctColleague *)event {

}
@end

接着创建具体类Colleague和TypeOneMediator分别继承抽象类AbstrctColleague和AbstractMediator,并实现其方法。

Colleague.h

#import <UIKit/UIKit.h>
#import "AbstrctColleague.h"

@interface Colleague : AbstrctColleague
@property (nonatomic, assign) CGFloat value;

// 修改数值
- (void)changeValue:(CGFloat)value;
@end

Colleague.m

#import "Colleague.h"

@implementation Colleague

- (void)changeValue:(CGFloat)value {
    self.value = value;
    if (self.delegate && [self.delegate respondsToSelector:@selector(colleagueEvent:)]) {
        
        [self.delegate colleagueEvent:self];
    }
}

@end

TypeOneMediator.h

#import "AbstractMediator.h"
#import "Colleague.h"

@interface TypeOneMediator : AbstractMediator

@property (nonatomic, strong) Colleague *colleagueA;
@property (nonatomic, strong) Colleague *colleagueB;
@property (nonatomic, strong) Colleague *colleagueC;


// 查看信息
- (NSDictionary *)values;

@end

TypeOneMediator.m

#import "TypeOneMediator.h"

@implementation TypeOneMediator

// 主要用来查看打印信息.
- (NSDictionary *)values {
    return @{@"A":@(self.colleagueA.value),
             @"B":@(self.colleagueB.value),
             @"C":@(self.colleagueC.value),
             };
}

// 指定算法.
- (void)colleagueEvent:(AbstrctColleague *)event {
    
    if ([event isEqual:self.colleagueA]) {
        self.colleagueB.value = self.colleagueA.value * 2;
        self.colleagueC.value = self.colleagueA.value * 4;
        
    } else if ([event isEqual:self.colleagueB]) {
        self.colleagueA.value = self.colleagueB.value / 2.f;
        self.colleagueC.value = self.colleagueB.value * 2.f;
        
    } else {
        self.colleagueA.value = self.colleagueC.value / 4.f;
        self.colleagueB.value = self.colleagueC.value / 2.f;
    }
}

@end

最后,创建VC将中介者和多个同事给关联起来,中介者拥有多个同事对象,所有同事的代理对象设置为中介者。

ViewController.m

#import "ViewController.h"
#import "TypeOneMediator.h"
#import "Colleague.h"

@interface ViewController ()
@property (nonatomic, strong) TypeOneMediator *mediator;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.mediator = [TypeOneMediator new];
    
    Colleague *colleagueA = [Colleague new];
    Colleague *colleagueB = [Colleague new];
    Colleague *colleagueC = [Colleague new];
    
    self.mediator.colleagueA = colleagueA;
    self.mediator.colleagueB = colleagueB;
    self.mediator.colleagueC = colleagueC;

    colleagueA.delegate = self.mediator;
    colleagueB.delegate = self.mediator;
    colleagueC.delegate = self.mediator;
    
//    [colleagueA changeValue:2.f];
//    NSLog(@"%@", [self.mediator values]);
    
    [colleagueB changeValue:2.f];
    NSLog(@"%@", [self.mediator values]);
    
}

@end

深层次的应用:

       在一些特殊情况下,打开不同的页面(VC)之后,还需要传递一些命令到这个VC,让其做一些特殊的操作,于是可以通过配置URL的参数,再通过参数名和参数值传递给新VC:

[MRRouter openURL:@"scheme://test?aa=11&bb=22"];

更方便的,可以直接用字典来传递参数

[MRRouter openURL:@"scheme://test3" parameters:@{@"ccc":@"333",@"ddd":@"444"}];

于是还需要创建一个映射表,来建立URL和VC之间的映射关系,每增加一个VC,就在这个表里头增加一个对应关系。这里可以利用Objective-C的Runtime来动态地根据类名去映射,简化我们的日常编码操作,具体的实现就不在这里详细描述了,有兴趣可以去这里看具体的实现。

还可以定义一个默认的openURL操作:

[MRRouter sharedInstance].defaultExecutingBlock = ^(id object, NSDictionary *parameters) { 
    [self.navigationController pushViewController:object animated:YES];
};

这样在一般情况下打开一个新的页面,不需要引入任何头文件,也不需要建立映射关系,只需要调用Router的openURL接口。

通过以中介者模式为基础的Router管理页面的额外好处,就是可以简化服务端push需要打开新页面的操作,当有一个新的活动,要打开一个对应的页面,只需要把这个页面的URL通过push发送给客户端,客户端直接传递给Router即可,省略了大量的if/else的逻辑判断。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值