这个是老生常谈的问题,作为基础的软件开发模式,其革命性的思想奠定了当前软件开发的主流架构思路。
简而言之,MVC将软件分为三层Model(模型层),View(视图层),Control(控制层)。
Model层对数据自身进行管理,提供对数据的基础操作,如增删改查等,对数据库,后台的访问等。总之,就是维持数据的合法性和一致性,并且跟视图和控制器没有任何依赖性,它不关心如何被视图显示(如柱状显示,表格显示等),也不关心如何被控制器操作(如增加数据项,修改数据项等)。它的变化通过向外发布通知的形式被视图知晓,而视图要具备这种侦测数据变化的能力,必须提前向该模型注册。这里面最能让人想到的就是Observer(观察者)模式。
View层,任务很单一,就是以某种形式显示模型的数据,保留一个刷新数据的机制,一旦自己所观察的数据模型发生了变化,则立即刷新自己。在Gof的建议中,View层的嵌套一般采用Composite模式来管理。
Control层的职能在于响应用户(View)的请求,如更新数据等,Control可能保持对Model的引用,一旦Control收到用户的请求,则它通过调用模型自身的接口,对数据进行操作,而模型的变化,会被侦测模型变化的View所知道,从而刷新数据。
也许,一般理解起来可能不怎么困难,但实际操作起来,要完全分清各个内容究竟属于那个层次,并不是一件容易的事情。从理论上讲,View上不应该处理任务逻辑,它只保留一个最基本的数据注入接口,一旦数据有变化,就自动刷新数据,但是实际操作中,多半都会有问题。要组织一个完善的数据结构,来对应一个复杂的视图,是有困难的。
另外,模型从远程获取的数据并不一定就完全能被View直接使用,多半要经过“合法化”,而这个“合法化”的过程,一般放在Model层内部处理,我们通常会做一个代理(Proxy或者Delegate),来维持远程数据和数据模型的一致,而代理只对外提供操作模型的接口。如PureMVC的Proxy。
在用户请求对数据的操作中,Control接受到请求,会直接调用模型提供的接口。虽然Gof建议使用策略模式来实现,但在PureMVC和Cairngorm框架中,均采用了Command模式来实现Control响应View的请求。一条Command对应一个请求,Command基于一个状态,请求完毕就不复存在,剩下的就是Model和View之间的通信了。
在PureMVC中,有两个概念,域逻辑(domain logic)和业务逻辑(business logic)。域逻辑应该是指Model中维持自己合法性的逻辑,比如,从远程获取的数据,要解析成前端使用的数据,这个逻辑属于域逻辑;而业务逻辑,应该是应用程序的客户逻辑,比如,View中有一个人的速度一旦超过25,则精力消耗加速一倍,这种逻辑属于业务逻辑。一般的,域逻辑位于Model层,而业务逻辑位于Control层。