iOS-设计模式之胖瘦Model

前言

之前在自己公司开发过程之中,一直就是想办法把代码写的漂亮,可复用度高,就是不断地稠代码,分模块.具体怎么做
写出比较完美的代码,自己也不知道,现在有时间整理一些自己学习的心得,废话不多说,先飞一波!

这个问题,下次见面再回答你.jpg

在开始之前还是想讲一下,代码的规范

  • 先是life cycle,即controller的生命周期等一些方法如:
#pragma  mark - lifecycle
- (void)viewDidLoad 
  • 然后是 private method,一些私有方法(虽然说好的代码,控制器里面没有私有方法,不过毕竟不是超级大神),即你自己封装的一些功能类方法
#pragma  mark - private method
- (void)setupRefreshView 
  • 然后是Delegate方法实现,先系统代理,然后自己写的代理
#pragma  mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

#pragma  mark - SegmentCellDelegate
- (void)segmentClickedWithIndex:(NSInteger)selectedIndex
  • 然后是event response,所有button、gestureRecognizer的响应事件都放在这个区域里面,不要到处乱放。
#pragma mark - event response
//点击空白处释放键盘
- (void)tap 
//点击退出按钮
-(void)existButton:(UIButton *)button
  • 然后才是getters and setters,和 懒加载
#pragma mark - Getters and Setters
- (NSMutableArray *)searchSections {
    if (!_searchSections) {
        _searchSections = [[NSMutableArray alloc] init];
    }
    return _searchSections;
}

为什么要这样要求?

我见过无数ViewController,代码布局乱得一塌糊涂,这里一个delegate那里一个getter,然后ViewController的代码一般都死长死长的,看了就让人头疼。
定义好这个规范,就能使得ViewController条理清晰,业务方程序员很能够区分哪些放在ViewController里面比较合适,哪些不合适。另外,也可以提高代码的可维护性和可读性。

好了,希望以上可以帮到大家,这也是我看了一些文章整理出来常用 mark分类方法.下面开始主题了,一直听别人说关于胖瘦Model的事,也不是很了解,下面我们
来扒一下他们的老底.是不是有些期待呢....

一 丶关于胖Model和瘦Model

    1. 什么叫胖Model?

胖Model包含了部分弱业务逻辑。胖Model要达到的目的是:Controller从胖Model这里拿到数据之后,不用额外做操作或者只要做非常少的操作,就能够将数据直接应用在View上.

FatModel:
@property (nonatomic, copy) NSString *calId;            //日程id
@property (nonatomic, copy) NSString *title;              //日程标题
/*
 *  判断自己是否是该日程参与者
 */
+ (BOOL)isCalendarActory:(NSString *)doneUsers;

Controller:
    BOOL ret = [FatModel isCalendarActory:@“”];
其优点是:

这属于业务代码,算是弱业务。FatModel做了这些弱业务之后,Controller就能变得非常skinny,Controller只需要关注强业务代码就行了。众所周知,强业务变动的可能性要比弱业务大得多,弱业务相对稳定,所以弱业务塞进Model里面是没问题的。

另一方面,弱业务重复出现的频率要大于强业务,对复用性的要求更高,如果这部分业务写在Controller,类似的代码会洒得到处都是,一旦弱业务有修改(弱业务修改频率低不代表就没有修改),这个事情就是一个灾难。如果塞到Model里面去,改一处很多地方就能跟着改,就能避免这场灾难。

其缺点是:

胖Model相对比较难移植,虽然只是包含弱业务,但好歹也是业务,迁移的时候很容易拔出萝卜带出泥。另外一点,MVC的架构思想更加倾向于Model是一个Layer,而不是一个Object,不应该把一个Layer应该做的事情交给一个Object去做。最后一点,软件是会成长的,FatModel很有可能随着软件的成长越来越Fat,最终难以维护。

  • 2.什么叫瘦Model?

瘦Model只负责业务数据的表达,所有业务无论强弱一律扔到Controller。ThinModel要达到的目的是,尽一切可能去编写细粒度Model,然后配套各种helper类或方法来对弱业务做抽象,强业务依旧交给Controller。举个例子:

ThinModel:
@property (nonatomic, copy) NSString *calId;            //日程id
@property (nonatomic, copy) NSString *title;              //日程标题

ThinHelper:
/*
 *  判断自己是否是该日程参与者
 */
+ (BOOL)isCalendarActory:(NSString *)doneUsers;

Controller:
    BOOL ret = [ThinHelper isCalendarActory:@“”];
其优点是:

由于ThinModel跟业务完全无关,它的数据可以交给任何一个能处理它数据的Helper或其他的对象,来完成业务。在代码迁移的时候独立性很强,很少会出现拔出萝卜带出泥的情况。另外,由于ThinModel只是数据表达,对它进行维护基本上是0成本,软件膨胀得再厉害,ThinModel也不会大到哪儿去。

其缺点是:

缺点就在于,Helper这种做法也不见得很好,这里有一篇文章批判了这个事情。另外,由于Model的操作会出现在各种地方,ThinModel在一定程度上违背了DRY(Don't Repeat Yourself)的思路,Controller仍然不可避免在一定程度上出现代码膨胀。

二丶MVC

M应该做的事:
  1. 给ViewController提供数据
  1. 给ViewController存储数据提供接口
  2. 提供经过抽象的业务基本组件,供Controller调度
C应该做的事:
  1. 管理View Container的生命周期
  1. 负责生成所有的View实例,并放入View Container
  2. 监听来自View与业务有关的事件,通过与Model的合作,来完成对应事件的业务。
V应该做的事:
  1. 响应与业务无关的事件,并因此引发动画效果,点击反馈(如果合适的话,尽量还是放在View去做)等。
  1. 界面元素表达

三丶MVCS

苹果自身就采用的是这种架构思路,从名字也能看出,也是基于MVC衍生出来的一套架构。从概念上来说,它拆分的部分是Model部分,拆出来一个Store。这个Store专门负责数据存取。但从实际操作的角度上讲,它拆开的是Controller。

这算是瘦Model的一种方案,瘦Model只是专门用于表达数据,然后存储、数据处理都交给外面的来做。MVCS使用的前提是,它假设了你是瘦Model,同时数据的存储和处理都在Controller去做。所以对应到MVCS,它在一开始就是拆分的Controller。因为Controller做了数据存储的事情,就会变得非常庞大,那么就把Controller专门负责存取数据的那部分抽离出来,交给另一个对象去做,这个对象就是Store。这么调整之后,整个结构也就变成了真正意义上的MVCS。

TCStore:
//主要为本地数据查询,删除,跟新  提供接口
- (NSMutableArray *)fetchLocalFavoritesWithType:(NSString *)type
Controller:
self.dataSource = [[TCStore sharedInstance] fetchLocalFavoritesWithType:@“”];

四丶MVVM

1.纯属打酱油

MVVM去年在业界讨论得非常多,无论国内还是国外都讨论得非常热烈,尤其是在ReactiveCocoa这个库成熟之后,ViewModel和View的信号机制在iOS下终于有了一个相对优雅的实现。MVVM本质上也是从MVC中派生出来的思想,MVVM着重想要解决的问题是尽可能地减少Controller的任务。

2.看着好看有分割线

不管MVVM也好,MVCS也好,他们的共识都是Controller会随着软件的成长,变很大很难维护很难测试。只不过两种架构思路的前提不同,MVCS是认为Controller做了一部分Model的事情,要把它拆出来变成Store,MVVM是认为Controller做了太多数据加工的事情,所以MVVM把数据加工的任务从Controller中解放了出来,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。

3.卧槽怎么还有

MVVM是基于胖Model的架构思路建立的,然后在胖Model中拆出两部分:Model和ViewModel。关于这个观点我要做一个额外解释:胖Model做的事情是先为Controller减负,然后由于Model变胖,再在此基础上拆出ViewModel,跟业界普遍认知的MVVM本质上是为Controller减负这个说法并不矛盾,因为胖Model做的事情也是为Controller减负。

另外,我前面说MVVM把数据加工的任务从Controller中解放出来,跟MVVM拆分的是胖Model也不矛盾。要做到解放Controller,首先你得有个胖Model,然后再把这个胖Model拆成Model和ViewModel。

4.马上完了

前面扯了那么多,其实归根结底就是一句话:在MVC的基础上,把C拆出一个ViewModel专门负责数据处理的事情,就是MVVM。然后,为了让View和ViewModel之间能够有比较松散的绑定关系,于是我们使用ReactiveCocoa,因为苹果本身并没有提供一个比较适合这种情况的绑定方法。iOS领域里KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。

在实际iOS应用架构中,MVVM应该出现在了大部分创业公司或者老牌公司新App的iOS应用架构图中,据我所知易宝支付旗下的某个iOS应用就整体采用了MVVM架构,他们抽出了一个Action层来装各种ViewModel,也是属于相对合理的结构。
所以Controller在MVVM中,一方面负责View和ViewModel之间的绑定,另一方面也负责常规的UI逻辑处理。

viewCell
@property (nonatomic, strong) viewModel *model; 


Model
@property (nonatomic, copy) NSString *title;              //标题

viewModel
@property (nonatomic, strong) Model *model; 
/**
 * 头像frame
 */
@property (nonatomic, assign, readonly) CGRect headerFrame;        
+(void)caluCellHightWith:(RHFlowCategoryCellType)type;

Controller
viewCell.model = self.dataSource[index.row];

五丶VIPER

VIPER(View,Interactor,Presenter,Entity,Routing)。VIPER我并没有实际使用过,我是在objc.io上第13期看到的。

但凡出现一个新架构或者我之前并不熟悉的新架构,有一点我能够非常肯定,这货一定又是把MVC的哪个部分给拆开了(坏笑)。事实情况是VIPER确实拆了很多很多,除了View没拆,其它的都拆了。

这个我就不讲了,不怎么用,如果有想了解的,请去网站了解.

参考资料:
http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html
(objc.io)
https://www.objc.io/issues/13-architecture/viper/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容