Repository 资源库模式

这些内容来自 (英)Martin Fowler   的 《企业应用架构模式》。

协调领域和数据映射层,利用类似于集合的接口来访问领域对象。 

具有复杂领域模型的系统常常受益于一个层,比如由数据映射器提供的层,它分离了领域对象和数据库访问代码的细节。在这种系统中,有必要在集中了查询构造代码的映射层之上建立另外一个抽象层。当存在大量的领域类或者繁重的查询时,这样做就显得更重要。在这些特定情况下,增加该层可以使重复的查询逻辑最小化。

资源库协调领域和数据映射层,起到类似内存中领域对象集合的作用。客户对象以陈述的方式构建查询说明,并把它们提交给资源库以获取满足条件的对象。可以向资源库中增加对象,也可以从资源库中删除对象,就像这些对象来自一个简单的对象集合,并且由资源库封装的映射代码将根据实际情形执行相应的操作。从概念上来说,资源库封装了保存在数据存储中的对象集以及在这些对象上执行的操作,提供一个更加符合面向对象观点的持久层实现。资源库也支持在领域和数据映射层之间实现彻底分离和单向以来关系的目标。

 

运行机制

 

资源库是使用了本书中大量其他模式的一种高级模式。事实上,资源库看上去像面向对象数据库的一小块,从这个角度来说,它类似于查询对象,在此情况下开发小组往往会使用对象-关系映射工具而不是亲自创建它们。然而,如果开发小组已经采取了这一步,并创建了查询对象,则增加资源库功能就不难了。当和查询对象一起使用时,资源库不用增加很多操作就可以为对象-关系映射层添加很大程度的可用性。

不考虑隐藏在后台的所有机制,资源库表现为简单的查询接口。客户创建一个条件对象指定他们需要由查询返回的对象的特征。例如,要根据姓名来查找 Person 对象,首先创建一个条件对象,把每个单独条件设置成如:criteria.equals( Person.LAST_NAME, “Fowler”),及criteria.lik( Person.FIRST_NAME, ‘M’) 。然后调用repository.matching(criteria ) 返回一个领域对象的列表,该列表表示所有姓为 Fowler,名字已  M 开头的人。可以在一个抽象的资源库上定义各种类似于 matching( criteria ) 的便利方法;例如,当只需要一个匹配的对象时,soleMatch( criteria ) 可返回查找到的那个对象而不返回集合。其他常见的方法包括byObjectId( id ),它可以通过简单的调用 soleMatch 来实现。

对于使用资源库的代码而言,资源库看起来像一个简单的内存领域对象集合。领域对象本身通常不会直接存储在资源库中,这一事实并没有暴露给客户代码。当然,使用资源库的代码应该清楚,这个表面上的对象集合可能实际上映射为一个具有成百上千记录的产品表。在目录系统的 ProductRepository 上调用 all() 方法未必是一个好方法。

资源库用一个基于规约的对象选择方法来取代基于数据映射器类的特殊的查找器方法。这种方法与直接使用查询对象相比,后者的客户代码可能建立一个条件对象(规约模式的一个简单例子),在查询条件中直接提供 all() 函数,并执行查询。有了资源库,客户代码创建条件,然后把它们传递到资源库,由资源库选择其中和条件匹配的对象。从客户代码的角度来说,不存在查询“执行”的概念;但是要根据满足查询对象规约的条件来选择适当对象。这看上去或许只是术语上的差别,但是它阐明了对象与资源库进行交互的好处,这也是其概念威力的一个很大部分。

在外表之下,资源库把元数据映射和查询对象结合起来,自动由条件生成 SQL 代码。无论条件是否知道如何把自身增加到查询中,查询对象都知道怎样合并条件对象,或者由元数据映射自身控制交互是实现的细节。

资源库的对象源可能根本不是关系数据库,这也没有问题,资源库能顺利通过特定的策略对象取代数据映射部分。因为这个原因,资源库对存在多数据库方案或者领域对象源的系统十分有用。另外,在以排他方式使用内存对象的测试代码中,有望获得比较快的速度。

资源库可以成为一种改善代码(这种代码会广泛使用查询)可读性和清晰性的好机制。例如,一个以具有许多查询页面为特征的基于浏览器的系统需要一个简洁的机制来处理由 HttRequest 对象得到的查询结果。如果不能自动转换,该请求的处理程序代码通常能在不带来较多混乱的情况下把 HttpRequest 对象转换为条件对象;把条件提交给适当的资源库仅仅需要增加额外的一行或者两行代码。

 

使用时机

 

在需要领域对象类型和许多可能查询的大型系统中,资源库减少了用于处理所有要执行查询的代码总量。资源库改进了规约模式(这里以条件对象的形式),规约模式以纯面向对象的方式封装了要执行的查询。因此,可以删除所有对特例建立查询对象的代码。客户从来不比考虑 SQL,而仅仅根据对象来写代码。

然而,在多数据源的情况下将真正看到资源库的作用。例如,假设有时我们想使用简单的内存数据存储,通常是在为了获得较好性能而想完全在内存中运行单元测试的时候。没有数据库访问时,许多长德测试包运行的比较快。为单元测试创建固定的构件 ( fixture ) 同样比较简单,如果所做的只是构建一些领域对象并在建立时把它们放置在集合中,而不是保存在数据库中并在析构时删除它们。

当一个应用程序正常运行时,某些领域对象的确定类型应该一直被保存在内存中,对这种情况也可以考虑使用资源库。不变领域对象(那些不能被用户改变的对象)就是这样一个例子,这种对象一旦进入内存,就会一直保留在里面而且不会被再次查询。就像我们在本章后面将看到的,一个简单的资源库模式的扩展允许根据情况采用不同的查询策略。

另外一个可以使用资源库模式的例子是当把数据输入当作领域对象源使用的时候,比如,互联网上的一个 XML 流(或许使用 SOAP)可以作为一个源使用。一个 XMLFeed RepositoryStrategry 可能被实现,它从 feed 中读取输入并从 XML 中创建领域对象。

资源库模式的两个特点: 

行为类似内存中的集合

查询规约提交到资源库

猜你喜欢

转载自blog.csdn.net/qq_33857502/article/details/79710264