词条统计
浏览次数:5561 次
编辑次数:1次 历史版本
最近更新:2013/6/20
创建者:掷鸡蛋者


使用MVC方式的开发,已经天然的将 controller / model / view 进行了分离,因此这三个部分不能算是分层,而应该算是项目内在的结构。

我们这里的分层是指,将 controller 中用到 domain model 部分的代码给隔离出去。这个新添加的层,我们叫做 service 层(服务层),它的作用在于向 controller 提供服务。controller 需要什么对象、需要如何操作对象,全部委托给 service 去干。

先看一下目前的方案:

而我们目前的项目中使用了另一种方案:直接操作领域对象:

比如上面的代码,直接通过领域对象 Category 检索(findAll) 出所有分类。

这种让领域对象具有直接行动能力的方式,我们称之为“充血模型”。相对应的是“贫血模型”,就是对象 Category 没有相应的能力,只是简单的属性的集合。您可以看到,一旦使用了wojilu ORM,也然是让领域对象继承了 ObjectBase,它就天然的具有了持久化能力,也就是说它已经开始“充血”了。

充血模型简单直接,写出来的代码容易理解,非常适合快速开发。

那我们干嘛还要将它的行动能力分离出去,使用“贫血”模型呢?

答案是,为了二次扩展和性能优化。

分离出 serice 层,使用贫血模型

第一步:我们新建一个Service文件夹,并在里面添加 CategoryService :

为了简单起见,我们先随便实现了几个 CRUD 基本方法。您肯定注意到了,这个 service 只是简单的调用了 Category 从ORM继承来的持久化能力。为了尽量不要依赖领域模型的充血能力,我们修改成如下样子:

怎么改完之后,似乎连阅读性都差了点?没办法,贫血模型就是不如充血模型那么容易理解。

第二步:重构 controller 中领域模型操作的代码,使用 service :

请比较一下,被注释掉的代码和它下一行代码之间的区别。现在我们的controller不再依赖领域模型 Category 自身的能力,而是依赖于 CategoryService 对象。

不知道您有没有注意到,我们在声明 CategoryService 的时候,把它定义成了一个公共(public)属性。这是为了下面的解耦,待会儿再提。

第三步:建立 ICategorySerice:

首先我们使用重构方式提取接口:

然后将接口文件转移到一个interface的文件夹中,这样是为了代码结构更加清晰:


转移之后,您还需要稍微修改一下(比如给接口增加public),才能达到上面代码的效果。

第四步:在controller中使用 ICategorySerice:

请看第一处被注释掉的部分,通过使用接口,我们让controller不再依赖于具体的对象,为下面的解耦打下了基础。
至于 CategoryController 构造函数中直接new 了一个 CategoryService,只是给这个接口提供了一个默认实现而已