Objective-C小技巧 (Builder / Command / Protected)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lihei12345/article/details/80443904

Builder模式

当我们在设计一个类时,我们期望类属性的值由外部调用者传入,但是我们希望这个值仅在初始化设置,在初始化之后外部调用者修改这个值会导致状态混乱。或者干脆一个类具备大量外部可access的属性,调用者在使用这个类时会感觉比较茫然,需要一定的学习成本才能明白这个类设计的意图。我们可以通过Objective-C的 init 方法解决,尤其是 designated initializer,可以参考我之前的笔记,Objective-C新特性,但这个方式会导致调用方法可读性很差。

这类问题可以通过Builder模式很容易解决,但是发现大家日常使用并不多,可能Objective-C的惯例用法有关,如果大家接触过Android开发,就会发现Android的同学大量使用这个设计模式。iOS中实现这个模式稍微有些啰嗦,但是会大大简化调用代码,我认为成本还是合理的

调用代码:

Event *appearEvent = Event.eventBuilder(@"event").needDispatch(true).build();

头文件如下:

@class Event;
@interface EventBuilder : NSObject
- (EventBuilder *(^)(BOOL))needDispatch;
- (EventBuilder *(^)(dispatch_block_t))completionBlock;
- (Event *(^)(void))build;
@end

@interface Event : NSObject
// 头文件中属性声明为readonly,来确保对象是不可变对象
@property (nonatomic, copy, readonly) NSString *eventName;
@property (nonatomic, assign, readonly) BOOL needDispatch;
@property (nonatomic, copy, readonly, nullable) dispatch_block_t completionBlock;
// 唯一的设置入口是builder
+ (EventBuilder *(^)(NSString *))eventBuilder;

实现m文件如下:

@interface EventBuilder()
@property (nonatomic, strong) Event *event;
@end

#pragma mark - Event -

@interface Event()
// 在Extension中重写属性,所以内部可变
@property (nonatomic, copy, readwrite) NSString *eventName;
@property (nonatomic, assign, readwrite) BOOL needDispatch;
@property (nonatomic, copy, readwrite) dispatch_block_t completionBlock;
@end

@implementation Event

+ (EventBuilder * _Nonnull (^)(NSString * _Nonnull))eventBuilder
{
    return ^EventBuilder *(NSString *eventName) {
        EventBuilder *builder = [[EventBuilder alloc] init];
        builder.event.eventName = eventName;
        return builder;
    };
}

@end

#pragma mark - EventBuilder -

@implementation EventBuilder

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.event = [[Event alloc] init];
    }
    return self;
}

- (EventBuilder * _Nonnull (^)(BOOL))needDispatch
{
    return ^EventBuilder *(BOOL needDispatch){
        self.event.needDispatch = needDispatch;
        return self;
    };
}

- (EventBuilder * _Nonnull (^)(dispatch_block_t _Nonnull))completionBlock
{
    return ^EventBuilder *(dispatch_block_t completionBlock) {
        self.event.completionBlock = completionBlock;
        return self;
    };
}

- (Event * _Nonnull (^)(void))build
{
    return ^Event *(void) {
        return self.event;
    };
}

@end

Command模式

我经常在代码中是经常会遇到这样的场景:

if ([event.name isEqualToString:@"event_a"]) {
    // do something
} else if ([event.name isEqualToString:@"event_b"]) {
    // do something
} else if ([event.name isEqualToString:@"event_b"]) {
    // do something
}

如果比较简单的场景这样自然比较高效,但是如果比较复杂的场景,event类型比较多而且是易碎的业务代码的话,就会导致扩展性较差,而且互相耦合,导致修改一个逻辑会影响另外一个逻辑的代码。其实这个非常容易解决,把相应的逻辑封装为command,当然command模式的应用场景比这个要广很多。

Command定义:

@interface WMLogicCommand: NSObject
@property (nonatomic, copy) NSString *eventName;
@property (nonatomic, copy) void (^processEventBlock)(LogicController *, BusinessEvent *);
@end
@implementation WMHLLogicCommand

+ (LogicCommand *)createCommand:(NSString *)eventName processBlock:(void (^)(LogicController *, BusinessEvent *))processBlock
{
    LogicCommand *command = [[LogicCommand alloc] init];
    command.eventName = eventName;
    command.processEventBlock = processBlock;
    return command;
}
@end

处理代码:

for (LogicCommand *command in self.commands) {
     if ([command.eventName isEqualToString:event.name]
         && command.processEventBlock != NULL) {
         command.processEventBlock(self, event);
     }
 }

Protected

我们都知道Objective-C是语法比较弱的一门语言,尤其在access control方面,虽然支持继承,但是支持其实比较有限,有时我们从设计的角度比较希望实现protected控制,可以借助category头文件来实现,详细可以参考Masonry的源代码: Masonry源代码分析

猜你喜欢

转载自blog.csdn.net/lihei12345/article/details/80443904