The DoYouHaoBaby PHP Framework中文开发文档手册
Copyright(c) DoYouHaoBaby.NET All Rights Reserved.
[ 资源库 ]

在模型驱动设计中,对象从被创建开始,直到被删除或者被归档结束,是有一个生命周期的。一个构造函数或者工厂可应用来处理对
象的创建。创建对象的整体作用是为了使用它们。在一个面向对象的语言中,我们必须保持对一个对象的引用以便能够使用它。为了
获得这样的引用,客户程序必须创建一个对象或者通过导航已有的关联关系从另一个对象中获得它。例如,为了从一个聚合中获得一
个值对象,客户程序需要向聚合的根发送请求。问题是现在客户程序必须先拥有一个对根的引用。对大型的应用而言,这会变成一个
问题因为我们必须保证客户始终对需要的对象保持一个引用,或者是对关注的对象保有引用。在设计中使用这样的规则将强制要求对
象持有一系列它们可能其实并不需要保持的一系列的引用。这增加了耦合性,创建了一系列本不需要的关联。

要使用一个对象,则意味着这个对象已经被创建完毕了。如果这个对象是聚合的根,那么它是一个实体,它会被保持到一个被持久化
的状态
,可能是在数据库中,也可能是其他的持久化形式。如果它是一个值对象,它会通过一个实体经由对关联的导航来获得。我们
可以推导出大部分的对象可以从数据库中直接获取到。这解决了获取对象引用的问题。当一个客户程序需要使用一个对象时,它可以
访问数据库,从中检索出对象并使用它。这看上去是个非常快捷并且简单的解决方案,但它对设计会产生负面的影响。

数据库是基础设施的一部分。一个不好的解决方案是客户程序必须知道要访问数据库所需的细节。例如,客户需要创建sql 查询语句来
检索所需的数据。数据库查询可能会返回一组记录,甚至暴露其内部的更细节信息。当许多客户程序不得不直接从数据库创建对象
时,会导致这样的代码在整个模型中四散。从这点上讲领域模型做出了妥协。它必须处理许多基础设施的细节而不是处理领域概念。
如果我们做出了一个对数据库进行变更的变更那会怎么样呢?所有四散的代码需要变更以便能够访问新的存储。当客户代码直接访问
一个数据库时,它极有可能存储聚合中的一个内部对象。这会破坏聚合的封装性,带来未知的结果。

客户程序需要有一个获取已存在领域对象引用的实际方式。如果基础设施让这变得简单,客户程序的开发人员可能会增加更多的可导
航的关联进一步混乱模型。从另一方面讲,他们可能使用查询从数据库中获取所需的数据,或者拿到几个特定的对象,而不是通过聚
合的根来递归。领域逻辑分散到查询和客户代码中,实体和值对象变得更像数据容器。应用到众多数据库访问的基础设施的技术复杂
性会迅速蔓延在客户代码中,开发人员不再关注领域层,所做的工作跟模型无关了。最终的结果是丢失了对领域的关注,设计做了妥
协。

因此,使用一个资源库,它的目的是封装所有获取对象引用所需的逻辑。领域对象不需处理基础设施,以得到领域中对其他对象的所
需的引用。只需从资源库中获取它们,于是模型重获它应有的清晰和焦点。

资源库会保存对某些对象的引用。当一个对象被创建出来时,它可以被保存到资源库中,然后以后使用时可从资源库中检索到。如果
客户程序从资源库中请求一个对象,而资源库中并没有它,就会从存储介质中获取它。换种说法是,资源库作为一个全局的可访问对
象的存储点而存在。

资源库可能包含一定的策略。它可能基于一个特定的策略来访问某个或者另一个持久化存储介质。它可能会对不同类型的对象使用不
同的存储位置。最终结果是领域模型同需要保存的对象和它们的引用中解耦,可以访问潜在的持久化基础设施。




对于需要全局访问的每种类型的对象,创建一个新对象来提供该类型所有对象的内存列表的对应。通过一个共知的全局接口设置访
问。提供方法来增加或者删除对象,封装向数据存储中插入或者删除数据的实际操作。提供基于某种条件选择对象的方法,返回属性
值符合条件的完全实例化的对象或者一组对象,继而封装实际的存储和查询技术。仅对真正需要直接访问的聚合根提供资源库。让客
户程序保持对模型的关注,把所有的对象存储和访问细节委托给资源库。

资源库可能包含用来访问基础设施的细节信息,但它的接口应非常简单。资源库应该拥有一组用来检索对象的方法。客户程序调用这
样的方法,传递一个或者多个代表筛选条件的参数用来选择一个或者一组匹配的对象。实体可能通过传递其标识符被轻易指定。其他
选择条件可能由一组对象的属性构成。资源库将针对这组条件来比对所有的对象,并返回符合条件的那些对象。资源库接口可能包含
用来执行某些辅助计算(例如特定类型对象的数量)的方法。

看上去资源库的实现可能会非常类似于基础设施,但资源库的接口是纯粹的领域模型。

如图:


另一种选项是用规约(specification)指定一个查询条件。规约允许定义更复杂的条件:

如图:


工厂和资源库之间存在一定的关系。它们都是模型驱动设计中的模式,它们都能帮助我们关联领域对象的生命周期。然而工厂关注的
是对象的创建,而资源库关心的是已经存在的对象。资源库可能会在本地缓存对象,但更常见的情况是需要从一个持久化存储中检索
它们。对象可以用构造函数创建,也可以被传递给一个工厂来构建。从这个原因上讲,资源库也可以被看作一个工厂,因为它创建
对象。不过它不是从无到有创建新的对象,而是对已有对象的重建。我们将不把资源库视为一个工厂。工厂创建新的对象,而资源
库应该是用来发现已经创建过的对象。当一个新对象被添加到资源库时,它应该是先由工厂创建过的,然后它应该被传递给资源库以
便将来保存它,见下面的例子:
如图:


说明:另外要注意的是工厂是“纯的领域”,而资源库会包含对基础设施的连接,如数据库。