MVC模式
Model-View-Controller
-
model(模型):用来封装与应用程序相关的数据或处理数据的方法。
model对数据有直接访问权,它不关心自己会被如何调用。那些监视此model的view必须先在此model注册。 -
view(视图):用户看到的视图。一般不会包含业务逻辑代码,为了实现
view的刷新功能,必须先在监视的model上注册。 -
controller(控制器):起到不同层面的组织作用,用于控制应用程序的流程。它处理事件,并作出响应。"事件"包括用户行为和
model上的数据改变。

流程详解
1、首先用户操作view,会捕获到这个操作,并将控制权交给controller。
2、controller中进行业务逻辑操作,可能会改变model中的数据。
3、model中的数据发生改变,就会通过观察者模式通知view。
4、view通过观察者模式收到model数据变更的通知后,会向model请求新的数据,然后渲染页面。
注意
-
view只会把控制权交给controller,并不会执行业务逻辑代码。 -
controller只会执行业务逻辑代码并操作mdoel,不会改变直接改变view。 -
view和model的同步是通过观察者模式进行的,而同步操作是view自己请求model中的数据,然后更新视图。
优缺点
-
优点:实现了功能模块和显示模块的代码分离。同时还提高了系统的可维护性、可扩展性和可复用性。
-
缺点:简单的小型项目,使用MVC反而会降低开发效率。层与层虽然分离了,但是关联性太强了,没有做到独立的重用。
MVP模式
Model-View-Presenter
MVP由MVC演化而来,通过表示器(presenter)将视图和模型巧妙的分离开来。
-
model(模型):描述了系统的处理逻辑,对于表示器和视图一无所知。
-
view(视图):一般由表示器初始化,将用户输入转发给表示器。通常一个视图对应一个表示器,但是在业务逻辑复杂的情况下会对应多个。
-
presenter(表示器):表示器包含了大多数表示逻辑,用以处理视图。与模型交互以获取或更新数据。

流程详解
1、用户操作view,将控制权交给presenter
2、presenter执行业务逻辑,并更新model
3、model将自身的更新通过观察者模式通知presenter而不是view
4、persenter获取到model变更的通知后,通过view提供的接口,更新view
注意
view不再负责同步逻辑,而是由present负责,persent既有业务逻辑也有同步逻辑。这和MVC中的view同步逻辑不同,在MVC中是view直接使用model。view需要提供操作用户界面的接口给present调用(非常关键)
优缺点
优点:实现了model和view的真正完全分离,使模块职责划分明显。增加了程序可复用性(presenter可以复用)。隐藏了数据,提高了安全性。更加有利于单元测试。
缺点:增加了代码的复杂度,特别是对于小型程序,会使代码冗余。presenter中含有大量手动同步逻辑,会使得presenter很臃肿,难以维护。presenter如果与视图的交互过于频繁,那么就会使双方的联系过于紧密。不如预期那样降低耦合度和可复用性。
MVVM模式
Model-View-ViewModel
MVP模式的升级版本,将P换成了VM即ViewModel。MVVM有助于将用户界面的开发与业务逻辑或数据模型的开发分离开来。
ViewModel
"model for view",视图的模型。view需要什么数据,ViewModel就要提供什么数据。view有什么操作,ViewModel就要响应这个操作。
由于双向数据绑定,ViewModel发生改变,model也会更新。model发生改变,ViewModel也会更新。
调用关系

1、和MVP中的调用关系相同,ViewModel中有一个Binder。在MVP中,model和view的同步是通过presenter,而MVVM是Binder。
2、在view的模板语法中,通过指令声明视图中的内容与model中的哪一块数据绑定。
3、ViewModel更新model时,binder就会自动地更新view
4、用户操作view,binder就会自动地更新model。
也就是说MVVM将model和view的同步逻辑自动化了。以前交由presenter手动地进行model和view的同步,现在交给框架里提供的binder了。只需要在view的模板语法里声明内容对用model的哪一块数据。
优缺点
优点:双向数据绑定,开发者可以不用再关心如何去操作视图,而是改变model里的数据就可以了。分离了视图和模型,降低耦合度。
缺点:bug难以被调试,因为双向绑定,不知道是view层有问题还是model层代码有问题。数据绑定使得一个位置的bug被传到另一个位置,定位原始问题就不那么容易了。