MVC(Model-View-Controller)模型由Trygve Reenskaug博士在20世纪70年代提出,并 最早在面向对象编程语言 Smalltalk-80中实现。MVC强调将用户的输入、数据模型和数据表示方式分开设计,一个交互式应用系统由模型、视图和控制器3个部分组成,分别对应内部数据、数据表示和输入/输出控制部分,其结构如下图所示。
模型模型对象代表应用领域中的业务实体和业务逻辑规则,是整个模型的核心,独立于外在的显示内容和显示形式。模型对象的变化通过事件通知视图和控制器对象。采用了发布者/订阅者方式,模型是发布者,视图和控制器是订阅者。对于模型而言,并不知道自己对应的视图控制器;但控制器可以通过模型提供的接口改变模型对象,接口内封装了业务数据和行为。
视图视图对象代表GUI对象,用用户熟悉和需要的格式表现模型信息,是系统与外界的交互接口。视图订阅模型可以感知模型的数据变化,并更新自己的显示。视图对象也可以包含子视图,用于显示模型的不同部分。在多数的MVC实现技术中,视图和控制器常常是一一对应的。
控制器控制器对象处理用户的输人,并给模型发送业务事件,再将业务事件解析为模型应执行的动作;同时,模型的更新与修改也将通过控制器来通知视图,保持视图与模型的一致。
MVC的整个处理流程为:
系统拦截到用户请求,根据相应规则(多数采用路由技术)将用户请求交给控制器,控制器决定哪个模型来处理用户的请求;模型根据业务逻辑处理完毕后将结果返回给控制器;然后控制器将数据提交给视图;视图把数据组装之后,呈现给用户。其中,模型处理所有的业务逻辑和规则,视图只负责显示数据,控制器负责用户的请求,这样将业务和表现层分离,以便业务代码可以被用于任何相似的业务中,视图代码也可以根据需要随意替换。相比于传统地将业务逻辑和视图混合在一起的实现方式,MVC可以最大化地重用代码,且灵活性极高。
生命周期成本低 MVC使开发和维护用户接口的技术含量降低。
部署快 使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
可维护性高 分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。
有利软件工程化管理 由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。控制器也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。
没有明确的定义 完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。同时由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。
不适合小型,中等规模的应用程序 花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
增加系统结构和实现的复杂性 对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
视图与控制器间的过于紧密的连接 视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
视图对模型数据的低效率访问 依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
一般高级的界面工具或构造器不支持模式 改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,会造成MVC使用的困难。
模型-视图-表示器(Model-View-Presenter,简称 MVP)是近年来流行的一种体系结构。从名称上就可以看出,MVP与MVC十分类似,事实也确实如此。甚至有程序员开玩笑说MVP 不过是将MVC中的C换成了字母P,这种说法在一定程度上确实有其道理。 MVP从MVC演变而来,通过表示器将视图与模型巧妙地分开。在该模式中,视图通常由表示器初始化,它呈现用户界面(UI)并接受用户所发出命令,但不对用户的输入作任何逻辑处理,而仅仅是将用户输入转发给表示器。通常每一个视图对应一个表示器,但是也可能一个拥有较复杂业务逻辑的视图会对应多个表示器,每个表示器完成该视图的一部分业务处理工作,降低了单个表示器的复杂程度,一个表示器也能被多个有着相同业务需求的视图复用,增加单个表示器的复用度。表示器包含大多数表示逻辑,用以处理视图,与模型交互以获取或更新数据等。模型描述了系统的处理逻辑,模型对于表示器和视图一无所知。 MVP与MVC的主要差异体现在“请求在何处访问系统”,以及“各部分如何联系在一起”。MVP 的处理流程如下图所示。 MVP的整个处理流程为:
用户直接与视图进行交互(图中步骤1);视图通过引发一个事件,通知表示器有事件发生(步骤2),然后表示器访问视图以其IView接口所公开的属性(步骤3).这些属性是视图实际UI元素的包装器;此后表示器调用模型(步骤4),再返回结果(步骤5);表示器转换数据,然后设置UI的值,该操作通过IView接口完成(步骤6);视图将最终页面显示给用户。View与Model完全隔离 得益于此,Model和View之间具有良好的松耦合设计,这意味着,如果Model或View中的一方发生变化,只要交互接口不变,另一方就没必要对上述变化做出改变。这使得Model层的业务逻辑具有很好的灵活性和可重用性。
Presenter与View的具体实现技术无关 也就是说,采用诸如Windows表单,WPF,Web表单等用户界面构建技术中的任意一种来实现View层,都无需改变系统的其他部分。甚至为了使B/S,C/S部署架构能够被同时支持,应用程序可以用同一个Model层适配多种技术构建的View层。
可以进行View的模拟测试 过去,由于View和Model之间的紧耦合,在Model和View同时开发完成之前对其中一方进行测试是不可能的。出于同样的原因,对View或Model进行单元测试很困难。现在,MVP模式解决了所有的问题。在MVP模式中,View和Model之间没有直接依赖,开发者能够借助模拟对象注入测试两者中的任一方。