【MVVM的定义】
MVVM的目的是什么?
简单总结起来一句话:分离UI逻辑和业务逻辑。这一点和被大家熟知的MVP和MVC是一致的。
下面详细来说明下这个问题,下面一段英文来自Msdn:
The Model-View-ViewModel (MVVM) pattern helps you to cleanly separate the business and presentation logic of your application from its user interface (UI). Maintaining a clean separation between application logic and UI helps to address numerous development and design issues and can make your application much easier to test, maintain, and evolve. It can also greatly improve code re-use opportunities and allows developers and UI designers to more easily collaborate when developing their respective parts of the application.
Using the MVVM pattern, the UI of the application and the underlying presentation and business logic is separated into three separate classes: the view, which encapsulates the UI and UI logic; the view model, which encapsulates presentation logic and state; and the model, which encapsulates the application's business logic and data.
Prism includes samples and reference implementations that show how to implement the MVVM pattern in a Silverlight or Windows Presentation Foundation (WPF) application. The Prism Library also provides features that can help you implement the pattern in your own applications. These features embody the most common practices for implementing the MVVM pattern and are designed to support testability and to work well with Expression Blend and Visual Studio.
总结起来MVVM的好处有:
1、分离业务逻辑(buiness logic)和表现层逻辑(presentation logic)
2、Support testability 易于测试,正如martin flower 在xunit partten中提到的,对于程序unit test的建设要在设计之初便有所考虑。(对于这点是容易被很多人忽略的,因为多数coder甚至都不清楚什么叫Unit Test)而这一点事实上也是MVVM带来的很重要的好处。
3、从笔者的经历来看,mvvm的另一个意义在于,提高团队协作的效率。
为什么这么说呢?类比《设计模式》一书,设计模式这本书的重要作用在于,给程序员之间一个很好的名字契约,因此沟通时,只需要说我用了XX模式,那么对方很直观便明白了具体的实现。一个标准的架构的意义也在于此,比如团队使用MVVM来架构,那么只需要团队中的成员对MVVM有所了解,对各层的职责明确清楚,那么接下来继续要开展的工作就容易很多。这和招聘iOS研发要需要理解MVC是一个道理,大家都了解的统一的程序架构,是协作的很重要的前提。
看过了MVVM 的作用,我们接下来要做的便是明确各层的职责。单纯的把类名起名叫ViewModel却不做VM该做的事情,那还是建议压根就不要起名为VM来混淆试听了。(不能说拿来一个橙子告诉别人我这是橘子,而别人质疑的时候,辩解到这是改良的橘子)(虽然MVVM和MVX系列很相似,但他也是单独命名出来的,而不是叫做变种的MVP)
(因此建议不要再同其他人交流的过程中说,我用了MVVM架构,但说出来却完全不是那么回事儿,干脆说叫MVVMNB算了也免得产生误会)
【MVVM各层的职责界定】
为了权威仍然引用msdn中对于mvvm的各层的职责界定:
此图很清晰的明确了各层的职责以及交互方式,结合说明我们做进一步分析:
The View Class
The view's responsibility is to define the structure and appearance of what the user sees on the screen. Ideally, the code-behind of a view contains only a constructor that calls the InitializeComponent method. In some cases, the code-behind may contain UI logic code that implements visual behavior that is difficult or inefficient to express in Extensible Application Markup Language (XAML), such as complex animations, or when the code needs to directly manipulate visual elements that are part of the view. You should not put any logic code in the view that you need to unit test. Typically, logic code in the view's code-behind will be tested via a UI automation testing approach.
In Silverlight and WPF, data binding expressions in the view are evaluated against its data context. In MVVM, the view's data context is set to the view model. The view model implements properties and commands to which the view can bind and notifies the view of any changes in state through change notification events. There is typically a one-to-one relationship between a view and its view model.
To summarize, the view has the following key characteristics:
- The view is a visual element, such as a window, page, user control, or data template. The view defines the controls contained in the view and their visual layout and styling.
- The view references the view model through its DataContext property. The controls in the view are data bound to the properties and commands exposed by the view model.
- The view may customize the data binding behavior between the view and the view model. For example, the view may use value converters to format the data to be displayed in the UI, or it may use validation rules to provide additional input data validation to the user.
- The view defines and handles UI visual behavior, such as animations or transitions that may be triggered from a state change in the view model or via the user's interaction with the UI.
- The view's code-behind may define UI logic to implement visual behavior that is difficult to express in XAML or that requires direct references to the specific UI controls defined in the view.
很清楚的可以看出View的职责:
定义用户在屏幕中所看到的各个UI元素。
需要说明的是:
1、一般情况下在view的code behind里面应只包含构造函数,构造函数中执行InitilizeComponent方法。例外的场景是,在xaml中不容易实现的复杂的ui逻辑等。
2、不应将任何需要进行单元测试的逻辑放到view层中
3、在MVVM中View的DataContext是在ViewModel中。通常情况下View和ViewModel是一对一的关系
对于View层的理解比较简单
The View Model Class
The view model in the MVVM pattern encapsulates the presentation logic and data for the view. It has no direct reference to the view or any knowledge about the view's specific implementation or type. The view model implements properties and commands to which the view can data bind and notifies the view of any state changes through change notification events. The properties and commands that the view model provides define the functionality to be offered by the UI, but the view determines how that functionality is to be rendered.
The view model is responsible for coordinating the view's interaction with any model classes that are required. Typically, there is a one-to many-relationship between the view model and the model classes. The view model may choose to expose model classes directly to the view so that controls in the view can data bind directly to them. In this case, the model classes will need to be designed to support data binding and the relevant change notification events. For more information about this scenario, see the section, Data Binding, later in this topic.
The view model may convert or manipulate model data so that it can be easily consumed by the view. The view model may define additional properties to specifically support the view; these properties would not normally be part of (or cannot be added to) the model. For example, the view model may combine the value of two fields to make it easier for the view to present, or it may calculate the number of characters remaining for input for fields with a maximum length. The view model may also implement data validation logic to ensure data consistency.
The view model may also define logical states the view can use to provide visual changes in the UI. The view may define layout or styling changes that reflect the state of the view model. For example, the view model may define a state that indicates that data is being submitted asynchronously to a web service. The view can display an animation during this state to provide visual feedback to the user.
Typically, the view model will define commands or actions that can be represented in the UI and that the user can invoke. A common example is when the view model provides a Submit command that allows the user submit data to a web service or to a data repository. The view may choose to represent that command with a button so that the user can click the button to submit the data. Typically, when the command becomes unavailable, its associated UI representation becomes disabled. Commands provide a way to encapsulate user actions and to cleanly separate them from their visual representation in the UI.
To summarize, the view model has the following key characteristics:
- The view model is a non-visual class and does not derive from any WPF or Silverlight base class. It encapsulates the presentation logic required to support a use case or user task in the application. The view model is testable independently of the view and the model.
- The view model typically does not directly reference the view. It implements properties and commands to which the view can data bind. It notifies the view of any state changes via change notification events via the INotifyPropertyChanged and INotifyCollectionChanged interfaces.
- The view model coordinates the view's interaction with the model. It may convert or manipulate data so that it can be easily consumed by the view and may implement additional properties that may not be present on the model. It may also implement data validation via the IDataErrorInfo or INotifyDataErrorInfo interfaces.
- The view model may define logical states that the view can represent visually to the user.
需要注意的:
1、对于VM的职责,有一点非常容易理解错误,就是VM和Business logic的关系。
View Model 从名字来看就可以看出它是View的Model,因此它需要为View提供数据,以及操作接口,View Model中不应该包含Business Logic
2、VIewModel与View的关系如上面的图中所描述,ViewModel是不该知道View的,即ViewModel不该持有View的实例(It has no direct reference to the view or any knowledge about the view's specific implementation or type.)
3、ViewModel是可以脱离View和Model进行Unit Test的(the view model is testable independently of the view and the model.)
4、View通过Binding的方式将ViewModel中定义的数据以及行为(command)关联到一起
The Model Class
The model in the MVVM pattern encapsulates business logic and data. Business logic is defined as any application logic that is concerned with the retrieval and management of application data and for making sure that any business rules that ensure data consistency and validity are imposed. To maximize re-use opportunities, models should not contain any use case–specific or user task–specific behavior or application logic.
Typically, the model represents the client-side domain model for the application. It can define data structures based on the application's data model and any supporting business and validation logic. The model may also include the code to support data access and caching, though typically a separate data repository or service is employed for this. Often, the model and data access layer are generated as part of a data access or service strategy, such as the ADO.NET Entity Framework, WCF Data Services, or WCF RIA Services.
Typically, the model implements the facilities that make it easy to bind to the view. This usually means it supports property and collection changed notification through the INotifyPropertyChanged and INotifyCollectionChanged interfaces. Models classes that represent collections of objects typically derive from the ObservableCollection<T> class, which provides an implementation of the INotifyCollectionChanged interface.
The model may also support data validation and error reporting through the IDataErrorInfo (or INotifyDataErrorInfo) interfaces. These interfaces allow WPF and Silverlight data binding to be notified when values change so that the UI can be updated. They also enable support for data validation and error reporting in the UI layer.
The model has the following key characteristics:
- Model classes are non-visual classes that encapsulate the application's data and business logic. They are responsible for managing the application's data and for ensuring its consistency and validity by encapsulating the required business rules and data validation logic.
- The model classes do not directly reference the view or view model classes and have no dependency on how they are implemented.
- The model classes typically provide property and collection change notification events through the INotifyPropertyChanged and INotifyCollectionChanged interfaces. This allows them to be easily data bound in the view. Model classes that represent collections of objects typically derive from the ObservableCollection<T> class.
- The model classes typically provide data validation and error reporting through either the IDataErrorInfo or INotifyDataErrorInfo interfaces.
- The model classes are typically used in conjunction with a service or repository that encapsulates data access and caching.
需要说明的有:
1、Model层定义Business logic 和Data。
2、Model层不依赖于View和ViewModel层
总结
对于MVVM的职责划分正如上面所阐述的,很清晰,如此划分,我们可以很好的根据职责来组织代码的结构,增加程序的可维护性
综上,笔者的结论是,MVVM是配合WPF系列技术中Binding等强大特性而出现的一种程序的架构方式,清晰而简单,值得推荐使用。
参考:
http://en.wikipedia.org/wiki/MVVM
http://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
http://stackoverflow.com/questions/1644453/why-mvvm-and-what-are-its-core-benefits
更多关于MVVM的讨论欢迎加入qq群:182659848