What is the difference between the Data Mapper, Table Data Gateway (Gateway), Data Access Object (DAO) and Repository patterns?
我正在努力学习我的设计模式技能,我很好奇这些模式之间的区别是什么?所有这些看起来都是一样的——封装特定实体的数据库逻辑,这样调用代码就不知道底层持久性层。根据我的简短研究,所有这些方法通常都实现了您的标准CRUD方法,并抽象出了特定于数据库的细节。
除了命名约定(例如,customermapper与customerdao、customergateway与customerrepository),还有什么区别(如果有的话)?如果有区别,你什么时候会选择其中一个?
在过去,我会编写类似于以下内容的代码(简化,自然-我通常不会使用公共属性):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Customer { public long ID; public string FirstName; public string LastName; public string CompanyName; } public interface ICustomerGateway { IList<Customer> GetAll(); Customer GetCustomerByID(long id); bool AddNewCustomer(Customer customer); bool UpdateCustomer(Customer customer); bool DeleteCustomer(long id); } |
并且拥有一个
1 | Customer cust = CustomerGateway.GetCustomerByID(42); |
号
对于数据映射器和存储库模式,这似乎是相同的原则;DAO模式(我认为它与网关是相同的?)似乎也鼓励特定于数据库的网关。
我错过什么了吗?有3-4种不同的方法来做同样的事情似乎有点奇怪。
您的示例术语:datamapper、dao、datatablegateway和repository都有类似的用途(当我使用时,我希望返回一个客户对象),但其目的/含义和实现方式不同。
存储库"就像一个集合,除了具有更复杂的查询功能"[Evans,域驱动设计]并且可以被视为"内存中的对象外观"(存储库讨论)
数据映射器"在对象和数据库之间移动数据,同时使它们彼此独立以及映射器本身独立"(Fowler、Poeaa、Mapper)
TableDataGateway是"对数据库表的网关(封装对外部系统或资源的访问的对象)。一个实例处理表中的所有行(Fowler、Poeaa、TableDataGateway)
DAO"将数据资源的客户端接口与其数据访问机制分离/将特定数据资源的访问API适配为通用客户端接口",允许"数据访问机制独立于使用数据的代码进行更改"(Sun蓝图)
存储库似乎非常通用,不公开数据库交互的概念。DAO提供了一个接口,允许使用不同的底层数据库实现。TableDataGateway特别是一个围绕单个表的薄包装器。数据映射器充当一个中介,使模型对象能够独立于数据库表示(随着时间的推移)发展。
软件设计界有一种趋势(至少,我觉得是这样)为众所周知的旧事物和模式发明新的名称。当我们有了一个新的范例(可能与已经存在的事物略有不同)时,它通常会为每一层提供一整套新的名称。因此,"业务逻辑"变成了"服务层",仅仅是因为我们说我们做SOA,而DAO变成了存储库,仅仅是因为我们说我们做DDD(每一个实际上都不是新的和独特的东西,但是再一次:同一本书中收集的已知概念的新名称)。所以我不是说所有这些现代的范例和缩略词都意味着完全相同的事情,但你真的不应该太偏执。大多数都是相同的模式,只是来自不同的家庭。
数据映射器与表数据网关长话短说:
最后,它们都将充当内存中对象和数据库之间的中介。
你说得很有道理。选择你最熟悉的那个。我喜欢指出一些有助于澄清的事情。
表数据网关主要用于单个表或视图。它包含所有的选择、插入、更新和删除。所以客户是您案例中的一个表或视图。因此,表数据网关对象的一个实例处理表中的所有行。通常这与每个数据库表一个对象相关。
虽然数据映射器更独立于任何域逻辑,耦合度更低(尽管我认为要么存在耦合,要么不存在耦合)。它只是一个中间层,用于在对象和数据库之间传输数据,同时使它们彼此和映射器本身独立。
因此,通常在映射器中,您会看到插入、更新、删除等方法,在表数据网关中,您会找到getCustomerByID、getCustomerByName等。
数据传输对象不同于上述两种模式,主要是因为它是分布模式,而不是数据源模式。主要在使用远程接口的时候使用它,并且需要减少通话的聊天时间,因为每次通话都会变得昂贵。因此,通常设计一个DTO,它可以通过线序列化,将所有数据传回服务器,以应用进一步的业务规则或处理。
我对知识库模式不太熟悉,因为到目前为止,我还没有机会使用它,但我会查看其他人的答案。
以下只是我的理解。
表网关/行数据网关:在此上下文中,网关指的是一个特定的实现,它将每个"域对象"映射到每个"域对象网关"。例如,如果我们有Person,那么我们将有一个PersonGateway来将域对象Person存储到数据库中。如果我们有个人、员工、客户等,我们将有个人网关、员工网关和客户网关。每个网关将具有该对象的特定CRUD功能,并且与其他网关无关。这里没有可重用的代码/模块。网关可以进一步分为rowdatagateway或tablegateway,这取决于您是否传递了"id"或"object"。网关通常与活动记录进行比较。它将域模型与数据库模式联系起来。
repository/datamapper/dao:它们是相同的。它们都是指将数据库实体传输到域模型的持久层。与网关不同,存储库/datamapper/dao隐藏了实现。你不知道这个人背后是否有一个人通道。可能,也可能,你不在乎。您只知道它必须为每个域对象支持CRUD操作。它将数据源和域模型分离。