欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)

程序员文章站 2024-02-25 22:13:39
上一篇得到大家的关注,非常感谢。由于自己对于这些模式的理解也是有限,对于这些模式的比较,是结合自己的理解,一些地方不一定准确,但是只有亮出自己的观点,才能抛砖引玉不是? 欢...

上一篇得到大家的关注,非常感谢。由于自己对于这些模式的理解也是有限,对于这些模式的比较,是结合自己的理解,一些地方不一定准确,但是只有亮出自己的观点,才能抛砖引玉不是? 欢迎各位拍砖。:)

复制代码 代码如下:

阅读目录:

四. mvp模式

     4.1 mvp的思想

     4.2 ui界面接口化

     4.3 presenter —— model和view之间的桥梁

     4.4 mvp的代码结构和时序图

     4.5 mvp模式总结

五. mvvm模式

     5.1 mvvm模式的设计思想

     5.2 mvvm模式结构图

六. mvc, mvp和mvvm模式使用场景总结

四, mvp模式

mvp模式也是一种经典的界面模式。mvp中的m代表model, v是view, p是presenter。
下面例子中的完整代码,可以在这里下载:  winformmvp源码
大家还可以比较这篇文章 浅析mvp模式中v-p交互问题及案例分享

4.1 mvp的思想
mvp模式在我看来,是一个真正意义上的隔离view的细节和复杂性的模式。为什么这么说:
因为在其它模式中v都代表的是ui界面, 是一个html页面,xaml文件或者winform界面。但是在mvp模式中的v代表的是一个接口,一个将ui界面提炼而抽象出来的接口。接口意味着任何实现了该接口的界面,都能够复用已有的presenter和model代码。

4.2 ui界面接口化
要很好的理解mvp, 就要有把ui界面接口化的能力。看下面的界面中,将红色标记的user control抽象一下,就能得到下面的接口

ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)
 

复制代码 代码如下:

public interface iuseradd
{
       event eventhandler useraddevent;
       string username { get; set; }
       string userage { get; set; }
}

界面中的2个输入框被抽象成了username和userage两个属性。save按钮的点击事件,被抽象成了事件useraddevent。winform中实现该接口的代码如下:

复制代码 代码如下:

public partial class useradd : usercontrol, iuseradd
{
       public event eventhandler useraddevent;
       public string username
       {
           set { this.txbname.text = value; }
           get { return this.txbname.text; }
       }

       public string userage
       {
           set { this.txbage.text = value; }
           get { return this.txbage.text; }
       }

       public useradd()
       {
           initializecomponent();
       }

       private void btnadd_click(object sender, eventargs e)
       {
          if (useraddevent != null) useraddevent(this, e);
       }
   }

下面拿userage属性来解释一下,ui界面接口化的魔力。当后端代码要获取界面上的年龄值,就只需要get属性, 要更新界面显示的时候,就只需要set属性。
这个时候,后端代码对于界面的操作,被抽象成了对于userage属性的操作了,也就是和具体的界面显示无关了。

4.3 presenter —— model和view之间的桥梁
上文提到的后端代码中,包含了p和m. m和mvc中一样,指的是逻辑代码。p则是model和view之间的桥梁,负责将对应的model和view组合到一起。

针对上面的iuseradd, 对应的presenter代码是:

复制代码 代码如下:

public class useraddpresenter:ipresenter
{
       private readonly iuser _model;
       private readonly iuseradd _view;
       private readonly applicationfacade _facade = applicationfacade.instance; //这里的facade是presenter之间通信用的,详细可以看完整代码

      //presenter构造函数中,将view和model作为参数传入

       public useraddpresenter(iuser model, iuseradd view)
       {
           _model = model;
           _view = view;
           wireupviewevents();
       }

       private void wireupviewevents()
       {
           _view.useraddevent += _view_useradd;
       }

      //当view的useradd事件触发,取得ui中的数据,调用model逻辑处理,添加新用户。
     //同时发送user_added消息到系统中(系统中其它ui部分接收消息,比如这里的datagrid,它接收到user_added之后,会刷新)
       private void _view_useradd(object sender, eventargs e)
       {
           var user = new user
                      {
                          name = _view.username,
                          age = convert.toint32(_view.userage)
                      };
           _model.additem(user);
           _facade.sendnotification(applicationfacade.user_added);
       }
}

4.4 mvp的代码结构和时序图
这里的mvp中的代码结构图和时序图,能够更好的帮助理解mvp模式

ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)

ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)

4.5 mvp模式总结
在mvp里,presenter完全把model和view进行了分离,主要的程序逻辑在presenter里实现。而且,presenter与具体的 view是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更view时候可以保持presenter的不变,即重用! 不仅如此,我们还可以编写测试用的view,模拟用户的各种操作,从而实现对presenter的测试 —— 而不需要使用自动化的测试工具。 我们甚至可以在model和view都没有完成时候,就可以通过编写mock object(即实现了model和view的接口,但没有具体的内容的)来测试presenter的逻辑。

mvp的优势

1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——presenter内部
3、我们可以将一个presener用于多个视图,而不需要改变presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在presenter中,那么我们就可以脱离用户界面来测试这些逻辑(单元测试)

五, mvvm模式

5.1 mvvm模式的设计思想
mvvm模式中,一个viewmodel和一个view匹配,它没有mvp中的iview接口,而是完全的和view绑定,所有view中的修改变化,都会自动更新到viewmodel中,同时viewmodel的任何变化也会自动同步到view上显示。

这种自动同步之所以能够的原因是viewmodel中的属性都实现了observable这样的接口,也就是说当使用属性的set的方法,都会同时触发属性修改的事件,使绑定的ui自动刷新。(在wpf中,这个observable接口是 inotifypropertychanged; 在knockoutjs中,是通过函数ko.observable() 和ko.observrablecollection()来实现的)

所以mvvm比mvp更升级一步,在mvp中,v是接口iview, 解决对于界面ui的耦合; 而mvvm干脆直接使用viewmodel和ui无缝结合, viewmodel直接就能代表ui. 但是mvvm做到这点是要依赖具体的平台和技术实现的,比如wpf和knockoutjs, 这也就是为什么viewmodel不需要实现接口的原因,因为对于具体平台和技术的依赖,本质上使用mvvm模式就是不能替换ui的使用平台的.

5.2 mvvm模式结构图
这里是mvvm模式的结构图,能够帮助更加容易的理解mvvm模式:

ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)

六, mvc, mvp和mvvm模式使用场景总结

由于在winform中无法像wpf一样,支持数据和界面的双向绑定以及事件的监控,所以,在winform中mvp是最佳选择。
wpf和html界面中使用knockout,实现了observable, 所以使用mvvm.(应该说wpf就是为使用mvvm设计的)
在web应用中,由于http是基于请求和响应方式协同工作的, 无法一直保持连接状态,所以无法达到mvp中presenter之间的消息传递和mvvm中的viewmodel和界面之间的绑定, 所以mvc是最佳的选择。