代码改变世界

MVC, MVP, MVVM总结——MVC篇

2012-08-22 09:00  JustRun  阅读(1671)  评论(0编辑  收藏  举报

1. 这些模式诞生的源需求

程序的最原始的内容就是数据.

围绕着数据的产生、修改等变化,出现了业务逻辑, 围绕着数据的显示,出现了不同的界面技术.

没有设计的代码,会出现数据层(持久层)和业务逻辑层还有界面代码耦合的情况。

ORM解决业务逻辑和数据之间的耦合。

MVC, MVP, MMVM用来解决业务逻辑和视图之间的耦合

 

2. 经典的MVC模式

Model:

用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。Model有对数据直接访问的权力,例如对数据库的访问。

模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。

View:

视图层能够实现数据有目的的显示(理论上,这不是必需的)。

在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。

Controller:

控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。

image

 

3. 真实在Web中使用的MVC

 

image

 

上面是Structs中的MVC的一个请求的流程, asp.net中的MVC应该类似。

 

Web应用中的MVC架构与通常所说的MVC架构有一点区别。

主要区别在于:

在通常所说的MVC架构中,当model发生变化时,会主动更新对应的view视图,view与model是同步的.

而在web应用中,由于http是基于请求和响应方式协同工作的,因此当服务器端的model(数据)发生变化时,它不会立即更新客户端的view,只有客户端重新请求或刷新页面时才更新.

 

4. MVC的优点

  • 降低了系统的耦合性
  • 开发速度快,程序员和界面设计人员可以相对对立工作。
  • 可维护性高
  • 没有控件的概念,对html没有封装,易于理解
  • Asp.Net MVC和其它平台(java, php)等更加相似。便于人才获取

5. MVC使用的误区

 

  1. 把Model当做实体类(Entity),作为View和Controller之间的传输数据。
  2. 把业务逻辑全部放在Controller端,认为Controller是用来写UI的业务逻辑的。

这两个误区本质上都是对Model的作用不明导致的。

Model在MVC架构中起的作用非常重要,它才是UI业务逻辑真正的实现层。所以Model的实际上是Business Model(业务模型)。而Controller仅仅起一个“桥梁”作用,它负责把View的请求转发给Model,再负责把Model处理结束的消息通知View。Controller就是一个消息分发器。Controller是用来解耦View和Model的,具体一点说,就是为了让UI与逻辑分离(界面与代码分离)。

 

6. WinForm中的MVC

实现WinForm中的MVC是比Web复杂的事情,Controller要能够在Model和View之间自如游走的一个前提是对所有的事件进行拦截.

Web中的请求拦截非常容易,因为只有一个入口,而且很容易区分不同请求, 通过URL mapping来转向不同Model

PureMVC实现Winform MVC的, 它通过:

1. 每个界面视图(winform窗体或User Control)都对事件进行有意义的封装, 隔绝了View和逻辑

比如, Save按钮是添加一条新的User记录, 那么会在Save按钮的click事件中,调用一个Event。 而这个Event是由其它的逻辑代码实现的,不在这个视图中实现。

#region AddUser
public event EventHandler AddUser;   //event AddUser, 有意义的一个对外接口,交由外部实现,分离显示和逻辑

public virtual void OnAddUser(EventArgs args)
{
    if (AddUser != null) AddUser(this, args);
}
     #endregion 

private void btnAddUser_Click(object sender, EventArgs e)//按钮事件, 无意义
{
     _user = new User{Name=textBox1.Text, Age = Convert.ToInt32(textBox2.Text)};
    OnAddUser(e);
}

2. 每个视图对外提供传递显示数据的接口

如这里提供一个公开方法,显示一个IList<User>到界面上

  public void LoadUsers(IList<User> users)
  {
        this.dataGridView1.DataSource = null;
        this.dataGridView1.DataSource = users;
  }

3. 程序会为每个视图准备一个代理类(Mediator)

这个代理类会和对应的视图绑定,实现视图的public event, 调用Model, 也就是实际的逻辑代码

public UserAddMediator(UserAdd userAdd)
  :base(NAME, userAdd)
{
    userAdd.AddUser += new EventHandler(userList_NewUser);
}
void userList_NewUser(object sender, EventArgs e)
{
    var user = UserAdd.User;
    _userProxy.AddItem(user);//这里的_userProxy实际是Model层
    SendNotification(ApplicationFacade.USER_ADDED, user);//在系统中发送Notification, 感兴趣的人会截获并处理这个Notification, 下面有讲到。
    UserAdd.ClearForm();
}

调用视图的显示数据接口, 控制视图的呈现。

监听感兴趣的Notification和处理这些Notification

 

  public override IList<string> ListNotificationInterests()
  {
       IList<string> list = new List<string>();
       list.Add(ApplicationFacade.USER_ADDED);
       return list;
  }

  public override void HandleNotification(INotification note)
  {
      switch (note.Name)
      {
          case ApplicationFacade.USER_ADDED:
               UserList.LoadUsers(_userProxy.Users);
               break;
      }
  }

4. 整个最外层架构使用Facade模式, 解耦M和V, 通过Notification来串联整个系统。

 

 

PureMVC中没有关于WinForm的Demo代码,这里有一个简单的WinForm Demo.

WinformMVC.zip