iOS 面试锦囊之架构设计MVC、MVVM、MVP

💪💪
  • 对架构是如何理解的?
  • 讲讲MVC、MVVM、MVP,讲讲你项目里是如何具体体现的?
  • Controller 的臃肿问题何解?

一个好的架构应有的特点

  • 能把代码职责均衡的解耦到不同的功能类中,说简单一点就是 高内聚低耦合
  • 易用,维护成本低

如何解耦???
解决复杂性的最简单的方式就是多个实体间按照单一责任原则拆分职责。

优点:对Controller进行搜身,将View的内部的细节封装起来了,外接不知道View的内部具体实现
缺点:View依赖于Model,View绑定了模型

废话不得说,我们一起来看个简单的小demo. 简单的一个列表展示,分别用三种形式展现:


列表数据展示

从图中我们可以看到一个列表的展示,对几乎刚入门的开发者来说都是so easy,但是我们这里研究是架构模式,是一种思想。
Demo:

//ViewController继承自UITableViewController
#import "ViewController.h"
#import "HTTPRequest.h"
#import "MJExtension/MJExtension.h"
#import "NewsModel.h"
#import "NewsCell.h"
#define  Success [resposeObject[@"status"] isEqualToString:@"000000"]
@interface ViewController ()
@property(nonatomic,strong)NSMutableArray <NewsModel *>*dataArr;

@end
@implementation ViewController

#pragma mark - viewDidLoad
- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadDataFormNetwork];
}

#pragma mark - loadDataFormNetwork
- (void)loadDataFormNetwork{
    __weak typeof(self) weakSelf = self;
    [HTTPRequest GET:@"http://www.mocky.io/v2/5deb73662f0000690007e246" parameters:nil success:^(id  _Nonnull resposeObject) {
        
        if (Success) {
            weakSelf.dataArr = [NewsModel mj_objectArrayWithKeyValuesArray:resposeObject[@"data"]];
            [weakSelf.tableView reloadData];
        }
    } failure:^(NSError * _Nonnull error) {  }];
}

pragma mark - <UITableViewDataSource,UITableViewDelegate>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.dataArr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NewsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCellID" forIndexPath:indexPath];
    cell.model= [self.dataArr objectAtIndex:indexPath.row];
    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return [self.dataArr objectAtIndex:indexPath.row].cellHeight;
}
#pragma mark - setter && getter Method
- (NSMutableArray *)dataArr{
    if (!_dataArr) {
        _dataArr = [NSMutableArray array];
    }
    return _dataArr;
}
@end

Controller说明:从控制器导入的头文件中我们可以发现,控制器持有Model以及View,同时由控制器层发送网络请求,请求到数据之后将数据保存在Model中,控制器相当于Model与View的中介者。

/****************Model.h*********************/
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NewsModel : NSObject

@property(nonatomic, copy)NSString *title;
@property(nonatomic, copy)NSString *content;
@property(nonatomic, assign)CGFloat cellHeight;
@end
NS_ASSUME_NONNULL_END

/****************Model.m*********************/
#import "NewsModel.h"
@implementation NewsModel
- (CGFloat)cellHeight{
    
    if(_cellHeight == 0){
        CGFloat titleHeight  = 40;
        CGFloat bottomSpac = 10;
        NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
        attrs[NSFontAttributeName] = [UIFont systemFontOfSize:15];
        CGSize maxSize = CGSizeMake([UIScreen mainScreen].bounds.size.width - 2 * 12, MAXFLOAT);
        CGSize sizeToFit =    [self.content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
        _cellHeight += sizeToFit.height + titleHeight + bottomSpac;
    }
    return _cellHeight;
}
@end

Model说明:存放数据,并将cellHeight的高度进行保存,因为请求之后我们将数据保存到了模型中,从而我们知道模型中有哪些数据,从而对高度进行提前缓存。

/****************NewsCell.h*********************/
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
@class NewsModel;
@interface NewsCell : UITableViewCell
@property(nonatomic,strong)NewsModel *model;
@end

NS_ASSUME_NONNULL_END

/****************NewsCell.m*********************/
#import "NewsModel.h"
@implementation NewsCell
- (void)setModel:(NewsModel *)model{
    _model = model;
    self.textLabel.text  = model.title;
    self.detailTextLabel.text = model.content;
}
@end

View说明:简称UI层,负责显示数据,当View层状态发生改变时,会反击给控制器。


文字解读:
控制器用了Presenter,Presenter去处理UI以及业务逻辑,相当于取代了控制器的角色,从而又对控制器再次搜身,


MVVM

图片.png

共同点:跟MVP雷同,View和Model的很多逻辑都交给了VieModel处理
不同点:属性监听和绑定的问题,View可以监听ViewModel里面数据的改变,一旦发生改变,View的数据会自动更新(配合RAC更强大),不过笔记认为RAC这个框架体积过大,笔者觉得没必要用。
核心:View和ViewModel是双向绑定的,ViewModel可以负责创建拥有这个View,View又可以拥有这个ViewModel

MVC、MVVM、MVP就论绪到这里!!!
经过上面的讲解,相信你对Contoller的臃肿问题已经有了一些自己的见解。


对Controller 的臃肿问题,首先我们要先思考 什么样的内容才应该放到 Controller 中?,在我看来Controller 里面就只应该存放这些不能复用的代码

  • Controller 的臃肿问题何解?
    1、对于列表复杂的以及业务逻辑较多的可以将DataSource以及Delegate分离到另外一个类中
    2、将数据请求和业务逻辑分离到另外一个类中
    3、将拼装控件的逻辑,分离到另外一个类中

题外话
面试官打开自己的App,然后问你如果是你,你会怎么架构?

可以这样解答


图片.png

业务层也就是服务层
我个人对于逻辑的抽取,有以下总结。
可以将网络请求抽象到单独的类中
把网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:

  • 将网络请求与具体的第三方库依赖隔离,方便以后更换库。万一哪天第三库作者不维护了,更换起来容易
  • 方便在基类中处理公共逻辑。eg:统一处理公共参数(版本号、token、以及终端平台等等)笔者之前处理的单点登录以及异地登录。可以直接在封装的网络底层进行统一处理
    业务层我们可以负责处理登陆、以及支付模块的逻辑、订单的逻辑等等

总结

不要纠结于使用MVC、MVP还是MVVM,也不要为了装的显得逼格高一点而大材小用(eg:笔者讲的🌰,不过最主要在于是思想)。之所以会产生一些新的架构模式,是因为有些大型项目的业务逻辑越来越复杂,从而才会繁衍出新的花样,当然找到合适的才是最主要的!

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

推荐阅读更多精彩内容