标准的“模型视图控制器”模式和微软的模型/视图/视图模型模式之间有区别吗?
当前回答
MVC/MVVM不是一个非此即彼的选择。
这两种模式以不同的方式出现在ASP。Net和Silverlight/WPF开发。
ASP。Net, MVVM用于视图内的双向绑定数据。这通常是一个客户端实现(例如使用Knockout.js)。另一方面,MVC是一种在服务器端分离关注点的方法。
对于Silverlight和WPF来说,MVVM模式包含的内容更广泛,可以作为MVC(或其他将软件组织成独立职责的模式)的替代品。这种模式中经常出现的一个假设是,ViewModel简单地取代了MVC中的控制器(就好像你可以用VM代替C的首字母缩写一样,一切都可以原谅)……
ViewModel并不一定会取代对独立控制器的需求。
问题是:为了能够独立测试*,特别是在需要时可重用,视图模型不知道是什么视图显示了它,但更重要的是不知道它的数据来自哪里。
*注意:在实践中,控制器从ViewModel中删除了大部分需要单元测试的逻辑。VM就变成了一个不需要测试的容器,只需要很少的测试。这是一件好事,因为VM只是设计师和编码器之间的桥梁,所以应该保持简单。
即使在MVVM中,控制器也通常包含所有的处理逻辑,并决定使用哪个视图模型在哪个视图中显示哪些数据。
到目前为止,我们已经看到ViewModel模式的主要好处是从XAML后台代码中删除代码,从而使XAML编辑成为一个更加独立的任务。当需要时,我们仍然创建控制器来控制(没有双关语)应用程序的整体逻辑。
我们遵循的基本MVCVM指南是:
视图显示数据的特定形状。他们不知道数据从何而来。 ViewModels保存着特定形状的数据和命令,它们不知道数据或代码来自哪里,也不知道它是如何显示的。 模型保存实际数据(各种上下文、存储或其他方法) 控制器监听并发布事件。控制器提供了控制在哪里看到什么数据的逻辑。控制器为ViewModel提供命令代码,以便ViewModel实际上是可重用的。
我们还注意到,Sculpture代码生成框架实现了MVVM和类似于Prism的模式,它还大量使用控制器来分离所有用例逻辑。
不要认为控制器已经被视图模型淘汰了。
我已经开始了一个关于这个主题的博客,当我可以的时候,我会添加进去(只有当主机丢失时存档)。将MVCVM与通用导航系统相结合存在一些问题,因为大多数导航系统只使用视图和vm,但我将在后面的文章中讨论这个问题。
使用MVCVM模型的另一个好处是,在应用程序的生命周期中,只有控制器对象需要存在于内存中,并且控制器主要包含代码和少量的状态数据(即很小的内存开销)。与需要保留视图模型的解决方案相比,这大大减少了应用程序的内存密集型,并且非常适合某些类型的移动开发(例如使用Silverlight/Prism/MEF的Windows mobile)。这当然取决于应用程序的类型,因为您可能仍然需要保留偶尔缓存的虚拟机来响应。
注意:这篇文章已经编辑了很多次,并没有特别针对所提出的狭窄问题,所以我更新了第一部分,现在也包括了这个问题。在下面的评论中,大部分讨论只与ASP有关。而不是更广阔的图景。本文旨在介绍MVVM在Silverlight、WPF和ASP中的广泛使用。Net,并试图阻止人们用ViewModels替换控制器。
其他回答
一般来说,MVC用于Web开发,MVVM在WPF/Silverlight开发中最受欢迎。 然而,有时web架构可能混合使用MVC和MVVM。
例如:你可能会使用knockout.js,在这种情况下,你的客户端上会有MVVM。 你的MVC的服务器端也可以改变。在复杂的应用程序中,没有人使用纯模型。使用ViewModel作为MVC的“模型”可能有一定的意义,而你真正的模型基本上将是这个VM的一部分。这为您提供了一个额外的抽象层。
MVVM
视图➡视图模型➡模型
视图有对ViewModel的引用,反之则没有。 ViewModel有对模型的引用,反之则没有。 视图没有对模型的引用,反之亦然。
如果你正在使用一个控制器,它可以有一个视图和视图模型的引用,尽管控制器并不总是必要的,就像在SwiftUI中演示的那样。 数据绑定:我们为ViewModel属性创建侦听器,这样数据就可以通过视图模型从视图流向模型。虽然这些引用是单向的:View↔ViewModel↔Model,但数据需要流动:View↔ViewModel。视图如何通过读取自己的属性从模型中获取数据是很清楚的。数据绑定是如何在视图中检测事件并将它们反馈给模型。
class CustomView: UIView {
var viewModel = MyViewModel {
didSet {
self.color = viewModel.viewColor
}
}
convenience init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
}
struct MyViewModel {
var viewColor: UIColor {
didSet {
colorChanged?() // This is where the binding magic happens.
}
}
var colorChanged: ((UIColor) -> Void)?
}
class MyViewController: UIViewController {
let myViewModel = MyViewModel(viewColor: .green)
let customView: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
// This is where the binder is assigned.
myViewModel.colorChanged = { [weak self] color in
print("wow the color changed")
}
customView = CustomView(viewModel: myViewModel)
self.view = customView
}
}
设置的差异
业务逻辑保存在MVC的控制器中,MVVM的ViewModels中。 在MVC中,事件直接从视图传递到控制器,而在MVVM中,事件从视图传递到ViewModel再到控制器(如果有的话)。
共同的特征
MVVM和MVC都不允许视图直接向模型发送消息。 两者都有自己的模型。 两人都有自己的观点。
MVVM的优点
因为viewmodel包含业务逻辑,所以它们是更小的具体对象,便于进行单元测试。另一方面,在MVC中,业务逻辑在ViewController中。如果不同时测试所有的方法和侦听器,你怎么能相信视图控制器的单元测试是全面安全的呢?您不能完全相信单元测试结果。 在MVVM中,由于业务逻辑从控制器中被抽取到原子ViewModel单元中,ViewController的大小缩小了,这使得ViewController代码更加清晰。
MVC的优点
在控制器中提供业务逻辑减少了对分支的需求,因此语句更有可能在缓存上运行,这比将业务逻辑封装到ViewModels中性能更好。 在一个地方提供业务逻辑可以加速不需要测试的简单应用程序的开发过程。我不知道什么时候不需要检查。 对于新开发人员来说,在ViewController中提供业务逻辑更容易考虑。
首先,MVVM是使用XAML处理显示的MVC模式的发展。本文概述了这两者的一些方面。
模型/视图/视图模型架构的主要目的似乎是在数据(“模型”)之上,还有另一层非可视组件(“视图模型”),它将数据的概念更紧密地映射到数据的视图(“视图”)的概念。视图绑定的是ViewModel,而不是直接绑定模型。
简而言之,在MVC控制器中,ViewModel知道(控件)视图,而在MVVM中,ViewModel不知道谁使用它。ViewModel将其可观察属性和操作公开给任何可能对使用它感兴趣的人。这一事实使得测试更容易,因为在ViewModel中没有对UI的引用。
MVC/MVVM不是一个非此即彼的选择。
这两种模式以不同的方式出现在ASP。Net和Silverlight/WPF开发。
ASP。Net, MVVM用于视图内的双向绑定数据。这通常是一个客户端实现(例如使用Knockout.js)。另一方面,MVC是一种在服务器端分离关注点的方法。
对于Silverlight和WPF来说,MVVM模式包含的内容更广泛,可以作为MVC(或其他将软件组织成独立职责的模式)的替代品。这种模式中经常出现的一个假设是,ViewModel简单地取代了MVC中的控制器(就好像你可以用VM代替C的首字母缩写一样,一切都可以原谅)……
ViewModel并不一定会取代对独立控制器的需求。
问题是:为了能够独立测试*,特别是在需要时可重用,视图模型不知道是什么视图显示了它,但更重要的是不知道它的数据来自哪里。
*注意:在实践中,控制器从ViewModel中删除了大部分需要单元测试的逻辑。VM就变成了一个不需要测试的容器,只需要很少的测试。这是一件好事,因为VM只是设计师和编码器之间的桥梁,所以应该保持简单。
即使在MVVM中,控制器也通常包含所有的处理逻辑,并决定使用哪个视图模型在哪个视图中显示哪些数据。
到目前为止,我们已经看到ViewModel模式的主要好处是从XAML后台代码中删除代码,从而使XAML编辑成为一个更加独立的任务。当需要时,我们仍然创建控制器来控制(没有双关语)应用程序的整体逻辑。
我们遵循的基本MVCVM指南是:
视图显示数据的特定形状。他们不知道数据从何而来。 ViewModels保存着特定形状的数据和命令,它们不知道数据或代码来自哪里,也不知道它是如何显示的。 模型保存实际数据(各种上下文、存储或其他方法) 控制器监听并发布事件。控制器提供了控制在哪里看到什么数据的逻辑。控制器为ViewModel提供命令代码,以便ViewModel实际上是可重用的。
我们还注意到,Sculpture代码生成框架实现了MVVM和类似于Prism的模式,它还大量使用控制器来分离所有用例逻辑。
不要认为控制器已经被视图模型淘汰了。
我已经开始了一个关于这个主题的博客,当我可以的时候,我会添加进去(只有当主机丢失时存档)。将MVCVM与通用导航系统相结合存在一些问题,因为大多数导航系统只使用视图和vm,但我将在后面的文章中讨论这个问题。
使用MVCVM模型的另一个好处是,在应用程序的生命周期中,只有控制器对象需要存在于内存中,并且控制器主要包含代码和少量的状态数据(即很小的内存开销)。与需要保留视图模型的解决方案相比,这大大减少了应用程序的内存密集型,并且非常适合某些类型的移动开发(例如使用Silverlight/Prism/MEF的Windows mobile)。这当然取决于应用程序的类型,因为您可能仍然需要保留偶尔缓存的虚拟机来响应。
注意:这篇文章已经编辑了很多次,并没有特别针对所提出的狭窄问题,所以我更新了第一部分,现在也包括了这个问题。在下面的评论中,大部分讨论只与ASP有关。而不是更广阔的图景。本文旨在介绍MVVM在Silverlight、WPF和ASP中的广泛使用。Net,并试图阻止人们用ViewModels替换控制器。
推荐文章
- 在哪里放置AutoMapper.CreateMaps?
- 使用Enum实现单例(Java)
- 由Jon Skeet撰写的《Singleton》澄清
- 为什么c#不提供c++风格的'friend'关键字?
- Java / Jakarta EE web开发,我从哪里开始,我需要什么技能?
- 我能在视图中得到当前控制器的名称吗?
- 我应该使用什么MVVM框架?
- 什么是包装器类?
- MVC, MVP和MVVM设计模式在编码c#方面有什么不同
- MVVM:从开始到结束的教程?
- 安卓视图模型与视图模型
- 设计模式:工厂vs工厂方法vs抽象工厂
- 用MVVM处理WPF中的对话框
- WPF树视图中SelectedItem的数据绑定
- ViewModel应该如何关闭表单?