MVP詳解

1、概述

MVP的全稱為Model-View-Presenter,Model提供數(shù)據(jù),View負(fù)責(zé)顯示,Controller/Presenter負(fù)責(zé)邏輯的處理。MVP與MVC有著一個(gè)重大的區(qū)別:在MVP中View并不直接使用Model,它們之間的通信是通過(guò)Presenter (MVC中的Controller)來(lái)進(jìn)行的,所有的交互都發(fā)生在Presenter內(nèi)部,而在MVC中View會(huì)直接從Model中讀取數(shù)據(jù)而不是通過(guò) Controller。
MVP從視圖層中分離了行為(事件響應(yīng))和狀態(tài)(屬性,用于數(shù)據(jù)展示),它創(chuàng)建了一個(gè)視圖的抽象,也就是presenter層,而視圖就是P層的『渲染』結(jié)果。P層中包含所有的視圖渲染需要的動(dòng)態(tài)信息,包括視圖的內(nèi)容(text、color)、組件是否啟用(enable),除此之外還會(huì)將一些方法暴露給視圖用于某些事件的響應(yīng)。

2、MVP架構(gòu)和各層職責(zé)對(duì)比

image.png

在 MVP 中,Presenter 可以理解為松散的控制器,其中包含了視圖的 UI 業(yè)務(wù)邏輯,所有從視圖發(fā)出的事件,都會(huì)通過(guò)代理給 Presenter 進(jìn)行處理;同時(shí),Presenter 也通過(guò)視圖暴露的接口與其進(jìn)行通信。
各層職責(zé)如下:
VC層:

  • view的布局和組裝
  • view的生命周期控制
  • 通知各個(gè)P層去獲取數(shù)據(jù)然后渲染到view上面展示

controller層

  • 生成view,實(shí)現(xiàn)view的代理和數(shù)據(jù)源
  • 綁定view和presenter
  • 調(diào)用presenter執(zhí)行業(yè)務(wù)邏輯

model層

  • 業(yè)務(wù)邏輯封裝
  • 提供數(shù)據(jù)接口給controller使用
  • 數(shù)據(jù)持久化存儲(chǔ)和讀取
  • 作為數(shù)據(jù)模型存儲(chǔ)數(shù)據(jù)

Presenter層職責(zé)

  • 實(shí)現(xiàn)view的事件處理邏輯,暴露相應(yīng)的接口給view的事件調(diào)用
  • 調(diào)用model的接口獲取數(shù)據(jù),然后加工數(shù)據(jù),封裝成view可以直接用來(lái)顯示的數(shù)據(jù)和狀態(tài)
  • 處理界面之間的跳轉(zhuǎn)(這個(gè)根據(jù)實(shí)際情況來(lái)確定放在P還是C)

3、IOS中P層的具體實(shí)現(xiàn)

這是一個(gè)Presenter的Protocol, 所有的P層的類都要遵循這個(gè)Protocol

#import /**
  作為P : presenter 是管理 view viewController model這個(gè)三個(gè)中間人,負(fù)責(zé)UI刷新
  視圖的交互總是和VC 關(guān)聯(lián)著的
 */
@protocol TGPresenterProtocol @optional
// 處理View視圖相關(guān)操作 -- 協(xié)議的遵守者
- (void)setView:(NSObject *)view;
// 處理事件的相關(guān)響應(yīng)
- (void)setViewController:(UIViewController *)viewController;
// 展示
- (void)present;
// 加載model 
- (void)presentWithModel:(id)model viewController:(UIViewController *)viewController;
@end

可以看出, P層是可以拿到view或者viewController的, 并且可以在實(shí)現(xiàn)set方法的時(shí)候做一些事情. 這個(gè)稍后再講另外, P層還可以展示數(shù)據(jù), 直接展示數(shù)據(jù), present方法, 利用模型展示數(shù)據(jù), 利用presentWithModel:方法.比如, 在一個(gè)遵循了TGPresenterProtocol的Presenter類中,把需要管理的view傳遞給P

- (instancetype)initWithTableView:(UITableView *)view{

    self = [super init];
    if (!self) {
        return nil;
    }
    _view = view;
    _view.delegate = self;
    _view.dataSource = self;
    _view.separatorStyle = UITableViewCellSeparatorStyleNone;
    // 自適應(yīng)高度
    _view.rowHeight = UITableViewAutomaticDimension;
    _view.estimatedRowHeight = 100;
    return self;
}
- (void)setView:(UITableView *)view{
    // 設(shè)置視圖
    _view = view;
    _view.delegate = self;
    _view.dataSource = self;
    _view.separatorStyle = UITableViewCellSeparatorStyleNone;
    // 自適應(yīng)高度
    _view.rowHeight = UITableViewAutomaticDimension;
    _view.estimatedRowHeight = 100;
}

比如上面的代碼, 將tableView的數(shù)據(jù)源和代理都給了P, 那么P就相當(dāng)于行使了控制器的權(quán)力, 當(dāng)P層拿到數(shù)據(jù)時(shí)(P層是持有Model的):

- (void)loadHPData{

    NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"testCellData" ofType:@"json"];
    NSData *jsonData = [NSData dataWithContentsOfFile:dataPath];
    NSError *error;
    NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:&error];
    if (error) {
        NSLog(@"error = %@",error.localizedDescription);
    }
    NSLog(@"dataDic = %@",dataDic);
    // model 要處理好數(shù)據(jù)的顯示格式
    self.hpModel = [[CellSelfSizeModel alloc] initWithDic:dataDic];
    // 刷新
    [self present];

}

走Present方法, 實(shí)際就是tableView的reloadData,然后重走tableView的數(shù)據(jù)源方法. 將數(shù)據(jù)分發(fā)給cell去展示,這樣就實(shí)現(xiàn)了Controller, View, Model的解耦. 控制器做的事情只有如下幾件:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.title = @"MVP Demo";
//    布局
    [self initViews];
    [self setUpConstraints];

    self.hpPresenter = [TGHPPresenter new];
    // 視圖對(duì)象
    self.hpPresenter.view = self.tableView;
    // 控制器對(duì)象
    self.hpPresenter.viewController = self;
    // 外邊是要傳入?yún)⑦M(jìn)去的 -- 數(shù)據(jù)模型
    [self.hpPresenter loadHPData];

}

只需要初始化P層, 然后調(diào)P層的接口就可以了. 至于P層內(nèi)部的邏輯, 我不需要知道,其他的V層和M層。
1、V層也只專注于視圖的創(chuàng)建
2、M層只專注于模型的構(gòu)建(字典->模型)

4、MVP優(yōu)缺點(diǎn)

優(yōu)點(diǎn):
1、降低耦合度
2、模塊職責(zé)劃分明顯
3、利于測(cè)試驅(qū)動(dòng)開(kāi)發(fā)
4、代碼復(fù)用
5、隱藏?cái)?shù)據(jù)
缺點(diǎn):
1、由于對(duì)視圖的渲染放在了Presenter中,所以視圖和Presenter的交互會(huì)過(guò)于頻繁。如果Presenter過(guò)多地渲染了視圖,往往會(huì)使得它與特定的視圖的聯(lián)系過(guò)于緊密。一旦視圖需要變更,那么Presenter也需要變更了。

參考博客

https://blog.csdn.net/sheng52406/article/details/46679975/
http://m.itdecent.cn/p/a73953403fbf
https://baijiahao.baidu.com/s?id=1650972658696833051&wfr=spider&for=pc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載至:http://m.itdecent.cn/p/9a6845b26856 “Android MVP 詳解...
    SnowDragonYY閱讀 10,422評(píng)論 5 241
  • 作者:李旺成 時(shí)間:2016年4月3日 “Android MVP 詳解(下)”已經(jīng)發(fā)布,歡迎大家提建議。 MVP ...
    diygreen閱讀 129,363評(píng)論 85 1,320
  • 一、MVC 從字面意思來(lái)理解,MVC 即 Model View Controller(模型 視圖 控制器),是 X...
    032c6843a285閱讀 20,896評(píng)論 21 46
  • 5. 最佳實(shí)踐 好了終于要點(diǎn)講自己的東西了,有點(diǎn)小激動(dòng)。下面這些僅表示個(gè)人觀點(diǎn),非一定之規(guī),各位看官按需取用,有說(shuō)...
    SnowDragonYY閱讀 2,496評(píng)論 4 36
  • 作者:李旺成### 時(shí)間:2016年4月3日### 上篇 5. 最佳實(shí)踐# 好了終于要點(diǎn)講自己的東西了,有點(diǎn)小激動(dòng)...
    diygreen閱讀 30,630評(píng)論 54 492

友情鏈接更多精彩內(nèi)容