编程思想
1. 面向过程编程
根据业务逻辑从上到下写代码 。其往往用一长段代码来实现指定功能,开发过程的思路是将数据与函数按照执行的逻辑顺序组织在一起。
面向过程因为结构简单,没有类的概念,性能比面向对象更好。
面向过程的常用语言为C语言,一般嵌入式底层,操作系统底层都是使用面向过程编程思想,因为对于底层性能最重要。
2. 面向对象编程
在面向过程之上,增加了封装、继承、类、多态的概念。
面向对象思想更符合人的思维方式,实现的代码易维护、易扩张、易复用。
3. 链式编程
通过点语法来串联操作,把多个操作通过一行代码链接在一起的编程方式。优点是简化代码,提高代码可读性,更接近自然语言,Masonry设置约束语法使用链式编程思想实现。
4. 函数式编程
函数式编程与链式编程很相似,两者是不同角度思想,都可以提高代码可读性,也可以同时存在。
函数式编程是通过类似数学函数调用的方式实现值映射的效果,一般可通过嵌套调用来实现单向数据流,函数式编程关心调用顺序;链式编程重点在于通过点语法将操作连过程,不一定反应数据流动。
函数是"第一等公民",函数与其他数据类型一样,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。在ObjC中使用block来实现函数的效果。
链式编程:make.left.right.top.bottom.equalTo(0)
函数式编程:multi(add(2, 3), 10)
在ObjC中,链式编程一般通过带参数和返回值的Block作为返回值实现最终的传参与返回对象本身,比如 (返回对象类型 *(^)(传参类型))方法名 。
函数式编程通过block作为参数,对象本身作为返回值来实现,比如 - (返回对象类型 *)方法名:(新值 (^)(旧值))block名称,RAC,RXSwift都是使用函数式编程思想实现。
5. 响应式编程
响应式编程是一种面向数据流和变化传播的编程范式,其特点是变化传递。常见的RAC,RX系列,KVO都是响应式编程,响应式编程可用于实现MVVM中的双向绑定关系。
6. 面向协议(接口)编程
将类与类之间的依赖关系转变为对协议(接口)的依赖,降低代码耦合度,便于维护扩展。
面向接口编程的典型设计模式是策略模式。
7. 面向切面编程
在不更改正常的业务处理流程的前提下,从一个切面介入,实现对目标对象嵌入附加的操作。比如常见的无痕埋点,日志统计,性能统计,异常处理一般都是使用面向切面编程思想来实现。
链式编程思想的实现
下面是OC语言实现的链式编程效果,不带有参数的方法 work和sleep,带有参数的方法 hello。
下面两段调用代码是等效的,可以很明显看到,使用1这种链式编程的方式代码简单可读性非常强,接近自然语言。
下面我为UIView增加一个创建person的分类。
然后对其进行调用。
可以看到LJPerson的调用代码与Masonry几乎一致。Masonry内部链式编程的实现方案与LJPerson也基本上一样。
链式编程Masonry解析
Masonry是对NSLayoutConstraint 进一步面向对象 + 链式编程 的封装。
Masonry的文件结构如下图:
可以看到Masonry的内部实现很简单,除去分类,只剩下约束,约束属性和约束工厂。
MASLayoutConstraint继承自NSLayoutConstraint,与NSLayoutConstraint基本上等价。
MASConstraint是Masonry中约束的抽象类,主要包括两类接口。第一类是添加属性约束(left,right),第二类是设置约束值(offset,priorityLow,equalTo)。其中第二类最终都是调用抽象方法,需要在子类中具体实现。这两类接口都是使用链式编程方式,返回值是MASConstraint自身,使得设置约束信息可以用 . 符号串连起来,简化代码,并提高代码可读性。
MASViewConstraint继承自MASConstraint,是单个Masonry约束的实现类,内部封装了约束的相关信息,包含约束属性和参照属性MASViewAttribute,原始约束MASLayoutConstraint,约束视图和参照视图等。
MASCompositeConstraint是个复合约束,内部存储了多个MASViewConstraint。
MASCompositeConstraint复合类设计成MASConstraint是Masonry的亮点,这种设计一方面支持了链式语法(返回值为MASConstraint),一方面MASCompositeConstraint内部关于设置约束值的抽象方法,只需要遍历每个元素来执行MASViewConstraint实现的抽象方法即可。
MASConstraintMaker是个约束工厂类,另外负责管理单次make添加的所有约束。
MASConstraintMaker和MASConstraint都提供添加属性约束(left,right),后者最终会通过代理和前者一样调用MASConstraintMaker的如下方法。
所有的添加属性约束都会进入 constraint: addConstraintWithLayoutAttribute: 方法。
从方法可以看到,当添加了两次属性约束后,返回值为MASCompositeConstraint复合约束。
MASViewAttribute封装了属性NSLayoutAttribute和相关View。
下面为Masonry的类图。
我们都知道在使用masonry过程中,不需要进行weakSelf操作,可以从源码中得到答案。
可以看到,block使用完就丢弃了,并没有被View持有,此时整体的引用关系如下:
block->self
self->view
缺少view->block,无法构成循环引用。