好吧,我一直在尝试找出数据映射器和存储库之间的区别,但是到目前为止,我仍然没有。在我看来,专家程序员说:“存储库是在集中查询构造代码的映射层上的另一抽象层”。看起来可以理解,但仍然有些抽象。我之前读过这篇有关stackoverflow的文章,这让我更加困惑:How is the Data Mapper pattern different from the Repository Pattern?
我想我需要的是简单的解释和关于这两种模式如何不同以及存储库做什么而数据映射器没有做什么,反之亦然的具体/实践示例。你们中没有人知道一个很好的例子来说明数据映射器和存储库的概念吗?如果是相同的示例,则更好,一个示例使用数据映射器,另一个示例使用存储库。谢谢,我非常感谢。到目前为止,我还是很困惑...
假设您的应用程序管理Person
对象,每个实例都具有name
,age
和jobTitle
属性。
您想保留此类对象,从持久性介质中检索它们,并可能进行更新(例如,在其生日时增加年龄)或删除。这些任务通常在创建,读取,更新和删除中称为CRUD。
最好将“业务”逻辑与处理Person
对象的持久性的逻辑分离。这使您可以更改持久性逻辑(例如,从数据库更改为分布式文件系统),而不会影响业务逻辑。
您可以通过将所有持久性逻辑封装在Repository
后面来完成此操作。假设的PersonRepository
(或Repository<Person>
)将允许您编写如下代码:
Person johnDoe = personRepository.get(p=> p.name == "John Doe");
johnDoe.jobTitle = "IT Specialist";
personRepository.update(johnDoe);
这只是业务逻辑,并不关心对象的存储方式和位置。
在Repository
的另一侧,您同时使用了DataMapper
和用于将查询从功能描述转换为内容的内容(p=> p.name == "John Doe"
到持久层可以理解的内容)。
您的持久层可以是一个DB,在这种情况下,DataMapper
会将Person
对象与PersonsTable
中的一行进行转换。然后,查询翻译器将功能查询转换为SELECT * FROM PersonsTable WHERE name == "John Doe"
。
另一个持久层可以是文件系统,也可以是另一种选择将Person
对象存储在两个表PersonAge
和PersonJobTitle
中的DB格式。
[在后一种情况下,DataMapper
的任务是将johnDoe
对象转换为两行:一列用于PersonAge
表,另一列用于PersonJobTitle
表。然后,查询逻辑需要将功能查询转换为两个表上的join
。最后,DataMapper
需要知道如何根据查询结果构造Person
对象。
在大型,复杂的系统中,您希望使用小型组件来完成细小,明确定义的事情,并且可以独立开发和测试:
Repository
,而不关心它是如何[。Repository
要在特定持久性介质中读取/写入对象时处理DataMapper
。Repository
依赖于DataMapper
提供的架构(例如,在jobTitle
表的JobTitle
列中找到PersonTable
值),但不依赖于任何DataMapper
依赖于[阅读PoEAA(Martin Fowler)之后,我也难以识别数据映射器和存储库之间的差异。
这是我发现这两个概念最终归结为:
Repositories
是一个通用概念,不必一定要存储到数据库中,它的主要功能是提供对域对象的访问(如启用查询的访问)(无论它们是从数据库获取的)除了重点)。存储库可能(并且经常会)包含DataMappers本身。DataMappers
充当域对象和数据库之间的中间层,从而使它们可以独立发展,而彼此之间互不依赖。数据映射器可能具有“查找”或查询功能,但这并不是它们的主要功能。您发现您在DataMappers中使用复杂的查询逻辑的次数越多,您就越想开始考虑将查询逻辑解耦到存储库中,同时又让DataMappers充当其主要功能,将域对象映射到数据库,反之亦然。