最后开始做一些Silverlight开发,我遇到了MVVM。我熟悉MVC和我正在阅读的文章说因为XAML,MVC无法解决。没有太多的XAML经验是我没有理解这一点的原因。
有人可以解释为什么MVC不适合以及为什么MVVM更适合Silverlight开发?
由于 JD
答案 0 :(得分:58)
这是一个非常细微的区别,我可以通过比较ASP.NET中的MVC和WPF中的MVVM来解释它。
在ASP.NET MVC中,请求来自Web服务器,由Controller直接处理。 Controller确定适当的视图并使用模型填充它。然后,Controller将这些实例发布到底层系统,该系统将结果呈现给客户端。您可以看到Controller是第一个也是最后一个。
在MVVM中,UI(视图)面向用户并直接接受用户输入。在View中,ViewModel中的命令(View的DataContext)由此活动触发。控制流向ViewModel,ViewModel解释View发送的内容并准备其模型。控制流回View后,它会根据模型中的更改自行更新。如果需要新的View,ViewModel会将此与NavigationService(或您的应用程序使用的任何导航方法)进行通信,这是Window或Frame-UI组件的范围。您可以看到ViewModel不是第一个也是最后一个行为; View比MVC扮演更重要的角色。
WPF / Silverlight的体系结构是事情以这种方式完成的原因。控制器无法控制/替换命令,绑定和导航基础结构;它们与UI紧密集成。因此,控制器必须位于视图下方,并采取更为被动的角色。
答案 1 :(得分:13)
MVVM的设计主要是因为XAML,并且使数据绑定更简单,它与MVP非常相似。主要好处是操作用户界面的简单方法(ViewModel或Presenter负责该任务,而不是模型必须在Controller操纵后向View发送事件)。
我遇到的最好的两篇文章帮助我理解了这些原则MVC vs MVP vs MVVM和MVVM for Tarded Folks Like Me or MVVM and What it Means to Me
答案 2 :(得分:12)
去耦组件
在MVC中,组件之间存在三角关系。即:Controller拥有View和Model。 View依赖于Model的定义。模型需要满足View的要求。想想Hub(控制器)和辐条架构(视图和模型)
在MVVM中,想一想这个三角形在每个组件中变平,只知道链中的另一个组件。即:View-> ViewModel-> Model
模型不知道堆栈中的任何内容。 ViewModel只知道Model View只知道View Model - 它不知道Model。
为什么这很重要?
这是原始问题的核心。
主要目的是进一步抽象您的架构。这通常会导致更多代码,但对象之间的联系点更少。较少的联系点很重要,因为这会导致更敏捷的代码。 A类与B类的耦合/接触越多,A类变化的影响就越大。减少变更的影响是良好架构的关键优势之一。
要完全理解这一点,思考组件真正代表什么是有帮助的。什么是视图,控制器,ViewModel或模型?它们是文字定义,还是更多的抽象概念?
根据我的经验,将模型视为处理数据构造和持久性的类/对象集群更为有益。它不仅仅是一个具有属性的普通旧对象。它是一个执行数据提取,数据保存,构建普通旧对象的工厂的类。它是一个Facade层,为数据提供了清晰的API。该外观层是否应直接从View引用?
在我看来,它不应该。在MVC中,答案也是" no"。 Controller从模型中获取数据。在这方面,MVC和MVVM实现了相同的目标。这两种架构的不同之处在于数据和视图的关联方式。
与模型一样,View可以是一个类的集合,它们相互协调,呈现一个表示视图。对于移动平台(iOS上的View Controller,Android上的Activity),这可能包含View Controller + View。在很多情况下,您需要一个类将视图文档加载到内存中并更新视图属性。这里有很多工作要做。在MVC中,控制器迅速成为一个厨房水槽' class - 与当前用户上下文相关的任何事务的转储基础。
当您在应用程序中将数十个潜在视图相乘时,最终会在后端模型代码和前端View代码之间产生很多深度依赖关系。对于大型控制器类,这些依赖关系并不是很明显。
展平您的依赖关系
MVVM消除了依赖关系。这创造了焦点。什么是焦点?能够处理单个功能而不会分散所有其他依赖项。现在,您可以开始编写以前认为不可测试的代码的单元测试。
视图模型充当视图和模型之间的外观。 View Model满足View的需求 - 从技术上讲,View应该拥有View Model。如果View需要来自多个源的数据,则View Model会将单独数据源的组合封装到单个统一的非规范化对象中。如果视图需要回调到模型或其他目标,则视图模型提供挂钩并路由相应的调用。
考虑网络补丁面板的工作原理。乍一看,这似乎是多余的 - 为什么不简单地将您的以太网从A点连接到B点。但是根据经验,您将了解补丁面板为您提供了一个关键的抽象,允许您更改路径不影响A点的B点。这是您的View模型正在做的事情。
现在你的View和Model之间有一个干净的抽象,结果应该是你的View / Controller只关注表示。这意味着它不应该处理本地化或格式化 - 它获取数据并呈现数据。您的视图模型是进行这类预览数据按摩的理想场所。我们假设您需要根据条件过滤数据。同样,视图模型可以了解模型数据(您的视图不是),并且是放置此类代码的好地方。
一旦以这种方式开始组织应用程序需求,您的View / Controller代码就会变得更加清晰,当需要更改某些内容时,其含义会更加明显,从而减少错误。
<强>可测强>
关于可测试性的最后一点注意事项:通过展平依赖关系,可以更轻松地将模拟依赖项注入到测试中。它使测试更容易,更简洁。您的视图模型可以定义明确的测试用例。
答案 3 :(得分:4)
我认为这个想法是MVVM 更好适合XAML而不是MVC。说MVC'不适合'有点夸张。
为什么MVVM更好?主要是因为XAML中的数据绑定和命令绑定非常出色。见this article。
答案 4 :(得分:4)
我认为另一个好处是学习曲线。由于前端技术中的大多数开发人员都使用MVVM类型的编码风格,因此他们更容易采用与控制器模型相同的方式,他们需要将每个请求从视图传递到控制器并让它与模型进行通信。