版权声明:本文为博主原创文章,未经博主允许不得转载。 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源代码分析