JoshPell

人生只有必然,没有偶然

欢迎来到我的个人网站~


编程思想小觑

最近在研究RAC,发现编程思想这一个很有趣且有用的东西,就大概研究了一下“链式编程”、“函数式编程”、“响应式编程”几种主要的编程思想,发现对提高代码质量和业务水平很有帮助,下面就挨个介绍一下,也可以直接看我的DEMO

链式编程

思想特点

是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。类似a(1).b(2).c(3),方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)

代表

masonry框架、SDAutoLayout框架。

demo:

TJChainedModeClass *chainedMode1 = [TJChainedModeClass new];
chainedMode1.addName(@"jackson").addNickname(@"josh").addAge(5).addHeadImg(nil);

其中

chainedMode1.addName(@"jackson").addNickname(@"josh").addAge(5).addHeadImg(nil);

每一步点操作都会返回一个TJChainedModeClass实例对象,这样就可直接调取下一个点属性操作

这里贴出一个点操作函数,其他的都是类似形式

typedef TJChainedModeClass *(^configerString)(NSString *string);//这里的configerString是在.h文件中定义的返回值为本类对象的一个block,放这里方便查看

-(configerString)addName{
    
    if (!_addName) {
        
        __weak typeof(self) weakSelf = self;
        return ^(NSString *string){
            
            weakSelf.name = string;
            return weakSelf;
        };
    }
    
    return _addName;
}

响应式编程

思想特点

不需要考虑调用顺序,只需要知道考虑结果,类似于蝴蝶效应,产生一个事件,会影响很多东西,这些事件像流一样的传播出去,然后影响结果,借用面向对象的一句话,万物皆是流。是把操作尽量写成一系列嵌套的函数或者方法调用。

代表

KVO运用、ReactiveCocoa(也做函数响应式编程)。

demo

这里我选用KVO的方式来实现,其实方法很多,可以参考RAC。我这里是给本类的reactNum添加属性监听,有改变外部调用的地方也会执行block,而另外一个属性normalNum的改变则不会引起这种改变

.h中代码:

@property (nonatomic, assign) int reactNum;
@property (nonatomic, assign) int normalNum;

@property (nonatomic, copy) void (^reactBlock)(int num1,int num2);

.m实现:

-(instancetype)init{
    self = [super init];
    
    [self addObserver:self forKeyPath:@"reactNum" options:NSKeyValueObservingOptionNew context:nil];
    
    return self;
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    self.reactBlock(self.normalNum,self.reactNum);
    
}

调用:

-(void)reactProgramming{
    
    //类中的reactNum数值发生变化时,会调用打印方法
    TJReactiveProgrammingClass *reactObj = [TJReactiveProgrammingClass new];
    _reactObj = reactObj;
    
    //[reactObj TJ_addObserver:self forKeyPath:@"reactNum" options:NSKeyValueObservingOptionNew  context:nil];
    reactObj.reactBlock = ^(int normalNum,int reactNum){
        
        NSLog(@"normalNum:%d----reactNum:%d",normalNum,reactNum);
        
    };
}
//点击测试效果
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    _reactObj.reactNum = arc4random() % 100;//改变时会响应
    //_reactObj.normalNum = arc4random() % 100;//改变时不会响应
}

函数式编程

什么是函数式编程?函数式编程在iOS中是借由block实现的,通过声明一个block,类似于定义了一个“函数”,再将这个“函数”传递给调用的方法,以此来实现对调用该方法时中间一些过程或者对结果处理的“自定义”,而其内部的其他环节完全不需要暴露给调用者。实际上,调用者也根本不需要知道。

咱们来看一个例子:

[self.playBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.picView);
        make.width.height.mas_equalTo(50);
    }];

从中可以看出,Masonry中实现自动布局的关键类MASConstraintMaker,他的实例并不是调用者自己创建的,而是通过调用方法mas_makeConstraints:(这里是用了Category),其参数block中的参数传递过来的。

也就是说,通过mas_makeConstraints:这个方法,我们不需要知道MASConstraintMaker的实例是怎么创建的,也不需要知道具体是怎么实现了给View添加了自动布局,唯一需要的是实现(传递)一个block,在block里按照Masonry的方式指定需要添加的约束就可以了。

这种实现方式就是本篇要说的函数式编程。

函数式编程本质:

就是往方法中传入Block,方法中嵌套Block调用,把代码聚合起来管理

函数式编程特点

每个方法必须有返回值(本身对象),把函数或者Block当做参数,block参数(需要操作的值)block返回值(操作结果)

代表

Masonry、ReactiveCocoa(也做函数响应式编程)。

demo

现在有个类,它有一个NSString *finalString属性,我不想暴露给外部,在.h文件中我定义一个能传入外部blick的方法,和一个可以操作这个属性值的方法(可能类的内部需要这种操作,但又不想把属性暴露)

.h代码:

+ (NSString *)makeTool:(void(^)(TJFunctionalProgrammingClass *tool))block;

typedef TJFunctionalProgrammingClass *(^Function)(NSArray<NSString *> *strings);
@property (nonatomic, strong, readonly) Function FunctionalAction;

.m加入一个私有属性:

@property (nonatomic, copy) NSString *finalString;

.m方法实现:

+(NSString *)makeTool:(void (^)(TJFunctionalProgrammingClass *tool))block{
    
    if (block) {
        TJFunctionalProgrammingClass *tool = [[TJFunctionalProgrammingClass alloc]init];
        
        block(tool);
        
        return tool.finalString;
    }
    
    return nil;
}

-(Function)FunctionalAction{
    
    __weak typeof(self) weakself = self;
    return ^(NSArray<NSString *> *strings ){
        
        if (strings.count>0) {
            weakself.finalString = [NSString stringWithFormat:@"FunctionalProgramming + %@",[strings componentsJoinedByString:@"-"]];
        }else{
            weakself.finalString = @"FunctionalProgramming + nil";
        }
        
        return weakself;
    };
}

调用:

NSString *str = [TJFunctionalProgrammingClass makeTool:^(TJFunctionalProgrammingClass *tool) {
       
        tool.FunctionalAction(@[@"张三",@"李四",@"王五"]);
        
    }];
    
    NSLog(@"functionalProgramming----%@",str);

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

Powered by 谭健,分享从这里开始,精彩与您同在


正在加载中……