【应用MVP模式改进软件架构】软件架构模式

  摘 要: 模型-视图-控制器 (MVC) 模式是一个框架级的设计模式,该模式将软件设计中的关注点分离开来,从而使程序更有弹性。随着软硬件的发展,基于MVC模式演化出了一些相关模式。模型-视图-表示器 (MVP) 模式就是由MVC演变而来。文章将首先介绍了可能的MVP模式的实现方法,然后讨论了该模式的应用,以及所带来的益处。
  关键词: 模式; MVC; MVP; 软件架构
  中图分类号:TP302.1 文献标识码:A 文章编号:1006-8228(2012)04-37-02
  Improving software architecture with MVP mode
  Wang Nianqiao
  (Wuhan technical college, department of electronic & information, Hubei, Wuhan 430074, China)
  Abstract: Applying the Model-View-Controller (MVC) mode shows that designing applications with different concerns makes programs more flexible. Several variations of it appeared over the years, and one of those is the Model-View-Presenter (MVP). In this article, one possible implementation of the MVP mode, its application and its benefits will be introduced.
  Key words: mode; MVC; MVP; software architecture
  1 MVP 概览
  MVP演变自MVC[1],通过表示器将视图与模型巧妙地分开。在该模式中,视图通常由表示器初始化,它呈现用户界面(UI)并接受用户所发出命令,但不对用户的输入作任何逻辑处理,而仅仅是将用户输入转发给表示器。通常每一个视图对应一个表示器。表示器包含大多数表示逻辑,用以处理视图,与模型交互以获取或更新数据等。模型描述了系统的处理逻辑,模型对于表示器和视图一无所知。
  [View][Presenter][Model]
  图1 MVP 模式
  MVP 中表示器通过接口(当然也可能是抽象基类)与视图交互[2,3]。采用这种方案可以使表示器自身成为一个可重用性和可测试性均很高的类。首先,表示逻辑独立于所使用的UI技术,因此,可在Windows和Web表示层中重用同一表示器。其次,针对某一接口为表示器编码,该表示器可以与实现该接口的任何对象交互,而实现该接口的可能是 Windows窗体对象、ASP.NET页面对象或者WPF窗口对象,这意味着只要视图接口不变,视图的任何更新都不会影响到表示器。再者,同一表示器可以处理同一应用程序的不同视图。比如,在软件即服务 (SaaS)中,应用程序托管在 Web 服务器上,并作为服务提供给每一个要求使用自定义 UI 的客户。最后,如果将应用逻辑混合于UI代码中,由于应用程序中的UI代码非常难以自动测试,从而导致整个应用的难以测试。因此,从UI分离出视图接口,将UI中的逻辑从视图中移除后,通过模仿视图对象,可以方便地测试表示器。
  当然上述所有优点不一定存在于所有情况,使用单一UI技术的应用就无法体现重用表示器的好处,但是无论如何,能够提高可测试性我们的研究就是非常值得的。
  2 MVP实践
  2.1 视图接口
  同MVC一样,MVP也是软件框架级的设计架构[4]。实现 MVP 模式时,要为每个视图定义抽象接口。接口标识视图支持的数据模型。无论哪种平台,每个逻辑上等效的视图都具有相同的接口。表示器通过此接口与视图交互。
  视图抽象包含视图可识别和可处理的模型,并且可以使用一些有用的特殊方法和事件来扩展模型,帮助表示器与视图之间实现流畅交互。下面是一个显示新闻的视图接口示例,视图上包含一个新闻列表,选中其中一项将显示具体的新闻内容。
  public interface INewsDetailsView {
  int NewsId { set; }
  string Title{ set; }
  …
  void AddNews(int newsId,string title,string authorName,datetime publishedDate,string content);
  }
  表示器与UI之间的任何交互都必须通过视图接口进行。 用户的任何命令都必须转发到表示器,并由其进行处理。如果表示器需要查询视图中的某些数据,或者将数据向下传递到视图,接口中应该有方法负责执行该操作。
  2.2 表示器
  视图中的控件将捕获任何用户操作并触发视图中的事件,例如按钮单击或索引选择更改事件。视图包含简单的事件处理程序,向负责视图的表示器分派调用。
  表示器类通常通过其构造函数接收对视图的引用。视图保留对表示器的引用,表示器保留对视图接口的引用,表示器不依赖于具体的视图对象。下面是一个显示新闻的表示器示例。
  public class NewsDetailsPresenter {
  private readonly INewsDetailsView view;
  public NewsDetailsPresenter(INewsDetailsView view) {
  this.view = view;
  …
  }
  public void Initialize() {
  …
  }
  public void ShowNewsDetails() {
  …
  }
  …
  }
  构造函数接收并保存对视图的引用,使用约定所表示的公共接口初始化视图。表示器类还包含大量方法,执行这些方法可响应来自 UI 的任何请求。任何单击或用户操作都与表示器类的方法绑定:
  private void OnSelectedIndexChanged(object sender,EventArgs e){
  presenter.ShowNewsDetails();
  }
  表示器使用视图引用访问输入值,并按同样方式更新 UI。
  2.3 实现视图接口
  视图接口使用某种UI技术的类实现。视图可能的类有 ASP.NET中的页面、Windows窗体中的窗体、WPF中的窗口和 Silverlight中的用户控件。首次加载视图时,它会创建其表示器类的一个实例,并在内部将其保存为一个私有成员。
  public partial class NewsDetailsView:Page,INewsDetailsView{
  private NewsDetailsPresenter presenter;
  protected void Page_Load(object sender,EventArgs e){
  presenter = new NewsDetailsPresenter(this);
  if(!IsPostback)
   presenter. Initialize();
  }
  public int NewsId {
  set { newsId_Label.Text = value.ToString(); }
  }
  public string Title {
  set { newsTitle_Label.Text = value; }
  }
  ...
  }
  视图中的属性是以可视控件上某些属性的包装形式实现的。例如,Title 属性是Label控件的Text属性的包装。重要的是,接口为表示器屏蔽了给定平台的UI详细信息。对于所创建的用于与INewsDetailsView接口交互的表示器类,可以处理实现该接口的任何对象,而无须涉及底层控件的编程接口的详细信息。
  MVP模式被分成两种单独模式,Supervising Controller 和Passive View[5]。Passive View中视图对模型一无所知;而Supervising Controller将会向视图中添加某些表示逻辑,比如使用数据绑定。实践中,很多时候都是这两种模式的混合体。
  2.4 应用程序导航
  表示器也负责在应用程序中导航。比如在同一个视图下,为响应用户命令打开一个对话框,可通过视图接口的成员(大多数是布尔值成员)来控制。若需要将控件传送到其他视图(和表示器),则可以创建一个表示应用程序控制器的静态类,用以确定下一个视图,其作用就是一个导航的中心控制台。
  复杂的导航可以通过工作流的方式来完成,最简单的也可能只要一个switch语句。工作流可以是任意形式,可以与实际工作流一样复杂,当然也可以与一个if语句序列那样简单。 在应用程序控制器中可按静态方式对工作流逻辑进行编码,也可以从外部可插入组件导入工作流逻辑。
  应用程序控制器中的实际导航逻辑将使用特定于平台的解决方案来切换到不同视图。对于Windows窗体,它使用特定方法打开和显示窗体;在ASP.NET中,它使用Response对象的Redirect方法。
  3 其他变体
  ASP.NET MVC基于MVC模式风格,与 MVP具有一些共同的特征。 MVC 中的控制器是视图与后端之间的调节器。控制器不保留对视图的引用,但会初始化模型对象,并使用中间组件(视图引擎)的服务将其传递到视图。
  WPF与Silverlight应用程序可能更适合模型视图-视图模型(MVVM )。MVVM是MVP的变体,将视图模型包含到表示器类中,表示器类公开视图将进行读写操作的公共成员。这是通过双向数据绑定实现的,双向绑定由框架提供内在支持。
  在 MVVM 中,视图与表示器类(视图模型)的属性被数据绑定,用户执行任何操作都会更新表示器中的这些属性,用户发出的任何请求(WPF 中的命令)都被表示器类的方法进行处理。表示器方法计算出的任何结果都存储在视图模型中,并通过数据绑定提供给视图。
  4 结束语
  MVP模式分离了应用程序的关注点,增强了代码的可测试性,但增加了应用程序中类的数量。对于小型程序而言,这可能会提高软件开发的成本。与此同时,大型应用程序更易于承担这些成本。因此,MVP 并不是对于开发任何应用程序都适用。无论如何,采用MVP后,根据表示视图的约定,设计人员和开发人员可以并行工作,这在任何开发中都是一个值得采用的实践方式。
  
  
  参考文献:
  [1] Martin Fowler. Patterns of Enterprise Application Architecture[M].人民邮电出版社,2009.
  [2] Robert C Martin, Micah Martin. 敏捷软件开发-原则、模式与实践(C#版)[M].人民邮电出版社,2008.
  [3] Dino Esposito, Andrea Saltarello. Microsfot.Net Architecting Applications for the Enterprise[M].人民邮电出版社,2009.
  [4] 温昱. 一线架构师实践指南[M].电子工业出版社,2009.
  [5] Peter Eeles, Peter Cripps.架构实战:软件架构设计的过程[M]. 机械工业出版社,2010.

推荐访问:架构 改进 模式 软件