iOS浅谈面向对象,以及对 MVP 设计模式的理解

最近公司项目不是很忙,这段时间就抽空给自己充了充电。在充电的同时顺手把项目中的网络请求给优化了一下,根据自己的想法加入了缓存和 json 格式检验,具体缓存思想可以看我这篇文章点我

在优化网络请求的同时也在网上查找一些比较优秀的三方库,其中看到猿题库封装的网络请求,其中关于猿题库网络请求介绍中:YTKNetwork 的基本的思想是把每一个网络请求封装成对象,这句话引起了我的思考,"对象"到底什么叫对象呢?什么叫面向对象呢?经过几天的思考终于悟出了一点门道,我将探索的过程分享出来希望能够对有需要的同学们有所帮助!

什么叫面向对象?

不懂就百度呗,在网上搜 iOS面向对象,出现最多的就是面向对象的三大特性:封装,多态,继承(这几个稍后说)。我们虽然用的是面向对象的语言,我相信绝大多数入门或者工作经验1年多的同学敲出来的代码依然是大段的面向过程的思想,我们只是把面向对象来当做 OC 语言的一个特性而已,具体是什么估计自己也说不明白到底是什么。

我曾问过一个同事什么叫面向对象,他是这么给我说的:一个自行车组装师傅,不需要知道车头的原理是怎么刹车的,只需要知道它是车头它的作用,就行,然后师傅组装自动车的其他部件,就可以把车装好,这就是面向对象,感觉他给我说的并非我所想问的。

对象的概念

什么是对象?世界万物皆对象,是啊,所有看到的看不到的都是对象,把对象引入到编程中,那就是面向对象编程(Object Oriented Programming,OOP,面向对象程序设计),在百度百科中有关于 OOP 详细的介绍。简单来说就是它将对象作为控件的基本元素, 利用对象和对象之间的相互作用来设计程序,说白了,一款软件的运行就是控件之间的相互作用。说了那么多,那到底啥是对象,对象是你,是我,是万物,我认为在程序中能 alloc出来的都是对象。就拿人来说,你是人,我也是人,为啥咱俩不一样,要是放到程序里来说,是因为 alloc 分配的内存地址不一样。人有头发,眼睛,手鼻等,这些在 OC 里面称之为属性,人能跑,跳,投,等动作这些在 OC 里面称之为方法。我这么比喻我想你应该有所理解。其实,你在做项目的时候已经在用对象这个概念了,只不过你不知道罢了。举个简单的例子:点击 tableview 的 cell 让 cell 里面的控件变换颜色,我相信大家都能实现这个效果,是怎么做的呢?肯定是定位点击的哪个 cell, 拿到当前 cell,那这个 cell 不就是对象,找到 cell 中的控件,控件不就是 cell 的属性吗?颜色也是控件的属性,控件即是对象也是属性,控件间的相互作用完成了这个功能,说到底也就是操作的对象。 大家做项目的时候都发起过网络请求,利用 AFN 的 POST 请求大家都经常用,那在请求回调的 block 块中返回的id responseObject这个是什么?对,这个就是对象,是一个数据对象,这个对象是由 AFN 创建,拿到数据对象,对数据做处理,我们怎么处理数据,一般我们是不是要建模型,那为什么我们要建模型,模型有什么特性呢?请看下面类的概念

类的概念

承接上面所说,模型有什么特性呢?具有相同数据,方法等。

面向对象编程中, 具体的事物是对象, 将具有相同或相似性质的对象的属性或方法抽象出来便是类,类是对象的抽象化,对象便是类的具体实现。估计这不好理解,再拿网络请求数据来讲,数据都有相同或相似的数据,将这段数据的相同点抽离出来便是我们所建的 model 类,比如 person 类,属性有:name,height,weight等,他们具有相同的属性将属性他们通过一个方法将数据进行转化,那这个方法不就是封装吗?一般都是在.h 文件中声明方法,在.m 中去实现,方法一般都是隐藏内部实现,预留一个稳定外部接口。面向对象程序设计中的方法可分为两种,一为上述的实体(对象)方法,二为类方法,主要的差异在于实体方法需要有一对象去引发,而类别方法可以由类别名称调用。

面向对象的三大特征

封装

上面在类的概念中已经将封装的概念带入了一点了,在网上对封装解释最多的就是:封装主要的功能是将数据隐藏起来,只有此类别所属的方法,亦即实体方法,才能直接存取数据,所以也可以说是在保护数据,不会被外界任意的存取,所以就大大的降低数据的误用,且很容易的知道错误在哪里,从而省下很多的维护成本。

继承

"继承"这俩字非常形象的描述了这一特性,我们现实生活中继承的发生着最多的就是"子继承父",它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展,大大提高了编程的灵活性。一般在项目里面会继承自 AFN 请求等即方便又快捷。

多态

不同对象以自己的方式响应相同的消息的能力叫做多态。假设有一个类,都有一个相同的方法, 比如这个方法叫-sport 小明和小红都继承自这一类,各自实现各自的- sport 方法,也就是不同的对象以自己的方式响应了相同的消息。

从理解面向对象到理解面向协议

网上传了一个很火的设计模式便是M-V-P,M V 大家必定熟悉,可能对 P 不是很了解, P 就是协议即protocol。 比如 TableView 的代理,每次在控制器或者视图中都要将协议写一遍,很繁琐,很麻烦。他们都有相同的数据和方法

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

...

这个设计模式将繁琐的协议抽离出来交给一个类去实现,只不过这个类实现是的是系统定义的协议。关于 MVP 简单使用可以看这个是我自己基于对象的理解用 swift 去实现的。

举个例子:
创建一个继承于NSObject类叫MTableViewDelegate。h文件,这个类实现的协议是UITableViewDelegateUITableViewDataSource

@interface MTableViewDelegate : NSObject<UITableViewDelegate,UITableViewDataSource>

大家在项目中都写过协议,声明协议,要实现协议,在MTableViewDelegate。m文件中要将 tableview 的代理方法要实现了,现在所有经过MTableViewDelegate所创建的对象都实现了 tableview 的代理

MTableViewDelegate *delegate = [[MTableViewDelegate alloc]init];

你在控制器中创建 tableview 你可以这样写

#import "MTableViewDelegate。h"
@interface ViewController ()
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, strong) MTableViewDelegate *delegate;
@end

- (UITableView *)tableView
{
    if (!_tableView) {
       UITableView * tableView = [[UITableView alloc] init];
        tableView。frame = self。view。bounds;
        //一定将代理设置为全局变量,如果设置为局部变量的话,
        没有了引用会自动被销毁(ARC)
        _delegate = [[MTableViewDelegate alloc]init];
        tableView。delegate = _delegate;
        tableView。dataSource = _delegate;
        [self。view addSubview:tableView];
        _tableView = tableView;
    }
    return _tableView;
}

这只是举了一个简单的不能再简单的例子了,只要为了说明面向对象的思想。万变不离其宗,无论是 MVP 还是 MVVM 或者是 MVC 都是基于对象去实现的,理解了对象的思想在以后做项目必有很大帮助。

推荐阅读更多精彩内容