MVC和MVP的简单理解

新接手的项目使用的整体 App 架构是 MVP 架构和我之前惯用的 MVC 架构并不一样,所以花时间重新熟悉了下这两个架构,发现了很多之前没有注意到的点,值得简单记录一下。

传统的 MVC 的架构如图

Untitled

MVC 最早是在20世纪80年代为程序语言 SmallTalk 发明的一种软件架构。但是传统的 MVC 和苹果改进后的 MVC 架构并不一样,苹果预期实现的 MVC 架构是这样子的。

Untitled

这种架构和上面传统的区别在于,下面苹果改进的这种 MVC 架构隔离了 View 和 Model,这两个组件想要通信必须要通过 Controller 才行。

我自己理解用简单的语言说就是,传统的 MVC 架构里 View 是可以持有 Model,并不需要通过 Controller。而下面这种 MVC 架构里 View 不能直接持有 Model,两者都需要被 Controller 持有,最终在 Controller 层面实现 View 和 Model 的通信。

在传统的 MVC 里,Controller是非常轻量级,它只是负责转发请求以及进行用户交互的响应,反而是 View 比较重需要做很多数据转换,一些业务逻辑。在苹果改进后的架构里 Controller 实现了较重的责任,View 只是作为展示层去进行展示,并不需要关心任何业务逻辑了。

事实上,苹果改进的这种架构并不算严格意义上的 MVC,叫它 MVP 更加合适。 结合上面的说法,MVC 和 MVP 之间的区别主要在于,是否对数据和视图模型进行隔离。

但是苹果自己在实现自己的 MVC 的时候出现了严重的问题,就是 View 和 Controller 混在一起,被 UIViewController 这个类统一实现了,如图所示

Untitled

View 和 Controller 没办法很好的拆分这个问题导致了 MassiveController 的出现,比如 Controller 应该不需要关心 View 的布局问题,但是 UIKit 框架在 UIViewController 里面设置了 viewDidLayoutSubviews 这样的布局入口函数,让开发者去进行视图布局,等等一坨坨代码就来了。

所以基于苹果 MVP 版本的改进版的 MVP 出现了,让 UIViewController 仅仅作为 View,引入 Presenter 作为 Model 和 View 的通信桥梁,我现在手头的新项目就是用这种架构做的。

一个摘自网上的 MVP Demo

import UIKit

struct Person { // Model
    let firstName: String
    let lastName: String
}

protocol GreetingView: class {
    func setGreeting(greeting: String)
}

protocol GreetingViewPresenter {
    init(view: GreetingView, person: Person)
    func showGreeting()
}

class GreetingPresenter : GreetingViewPresenter {
    unowned let view: GreetingView
    let person: Person
    required init(view: GreetingView, person: Person) {
        self.view = view
        self.person = person
    }
    func showGreeting() {
        let greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastName
        self.view.setGreeting(greeting)
    }
}

class GreetingViewController : UIViewController, GreetingView {
    var presenter: GreetingViewPresenter!
    let showGreetingButton = UIButton()
    let greetingLabel = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.showGreetingButton.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)
    }
    
    func didTapButton(button: UIButton) {
        self.presenter.showGreeting()
    }
    
    func setGreeting(greeting: String) {
        self.greetingLabel.text = greeting
    }
    
    // layout code goes here
}
// Assembling of MVP
let model = Person(firstName: "David", lastName: "Blaine")
let view = GreetingViewController()
let presenter = GreetingPresenter(view: view, person: model)
view.presenter = presenter

综上,还是要理解清楚 MVC 和 MVP,理清楚到底 MVC 到底是什么样子的,要不然 MVC 和 MVP 因为各种历史原因和不同人的不同理解就是傻傻分不清楚。

参考地址:

  1. iOS Architecture Patterns (opens new window)
  2. Concepts in Objective-C Programming-Model-View-Controller (opens new window)
  3. 浅谈 MVC、MVP 和 MVVM 架构模式 (opens new window)