139

我正在努力提高我的设计模式技能,我很好奇这些模式之间有什么区别?它们看起来都是一样的——封装特定实体的数据库逻辑,因此调用代码不知道底层持久层。根据我的简短研究,它们通常都实现了您的标准 CRUD 方法并抽象出特定于数据库的细节。

除了命名约定(例如 CustomerMapper vs. CustomerDAO vs. CustomerGateway vs. CustomerRepository)之外,有什么区别(如果有的话)?如果有区别,你什么时候会选择一个而不是另一个?

在过去,我会编写类似于以下的代码(自然是简化了 - 我通常不会使用公共属性):

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);
}

并有一个CustomerGateway为所有方法实现特定数据库逻辑的类。有时我不会使用接口并将 CustomerGateway 上的所有方法都设为静态(我知道,我知道,这使得它的可测试性降低)所以我可以这样称呼它:

Customer cust = CustomerGateway.GetCustomerByID(42);

这似乎与 Data Mapper 和 Repository 模式的原则相同;DAO 模式(我认为这与网关相同?)似乎也鼓励特定于数据库的网关。

我错过了什么吗?有 3-4 种不同的方式来做同样的事情似乎有点奇怪。

4

5 回答 5

101

您的示例条款;DataMapper、DAO、DataTableGateway 和 Repository,都有类似的目的(当我使用一个时,我希望得到一个 Customer 对象),但不同的意图/含义和结果实现。

存储库 “就像一个集合,除了具有更精细的查询能力” [埃文斯,领域驱动设计]并且可以被视为“内存外观中的对象”存储库讨论

DataMapper “在对象和数据库之间 移动数据,同时保持它们彼此独立以及映射器本身”Fowler,PoEAA,Mapper

TableDataGateway是“到数据库表的网关(封装对外部系统或资源的访问的对象)。一个实例处理表中的所有行”(Fowler,PoEAA,TableDataGateway

DAO “将数据资源的客户端接口与其数据访问机制分离/将特定数据资源的访问 API 适配为通用客户端接口”,允许“数据访问机制独立于使用数据的代码进行更改”Sun Blueprints

存储库似乎非常通用,没有暴露数据库交互的概念。DAO 提供了一个接口,可以使用不同的底层数据库实现。TableDataGateway 特别是单个表的瘦包装器。DataMapper 充当中介,使模型对象能够独立于数据库表示(随着时间的推移)而发展。

于 2009-05-02T09:12:16.080 回答
35

软件设计界有一种趋势(至少,我是这么认为的)为众所周知的旧事物和模式发明新名称。当我们有一个新的范式(可能与已经存在的东西略有不同)时,它通常会为每一层提供一整套新名称。所以“业务逻辑”变成了“服务层”,因为我们说我们做 SOA,而 DAO 变成了存储库,因为我们说我们做 DDD(实际上每一个都不是新的和独特的东西,但同样:新名称对于收集在同一本书中的已知概念)。所以我并不是说所有这些现代范式和首字母缩略词都意味着完全相同的东西,但你真的不应该对此过于偏执。这些大多是相同的模式,只是来自不同的家庭。

于 2009-05-02T08:41:33.017 回答
34

数据映射器与表数据网关 长话短说:

  • 数据映射器将接收域模型对象(实体)作为参数,并将使用它来实现 CRUD 操作
  • 表数据网关将接收方法的所有参数(作为原语),并且不会知道有关域模型对象(实体)的任何信息。

    最后,它们都将充当内存对象和数据库之间的中介。

  • 于 2013-06-24T14:41:50.777 回答
    15

    你有一个很好的观点。选择一个你最熟悉的。我想指出一些可能有助于澄清的事情。

    表数据网关主要用于单个表或视图。它包含所有的选择、插入、更新和删除。因此,在您的情况下,客户是表或视图。因此,表数据网关对象的一个​​实例处理表中的所有行。通常这与每个数据库表的一个对象有关。

    虽然 Data Mapper 更独立于任何域逻辑并且耦合较少(尽管我相信存在耦合或不耦合)。它只是一个中间层,用于在对象和数据库之间传输数据,同时保持它们彼此独立以及映射器本身。

    因此,通常在映射器中,您会看到诸如插入、更新、删除之类的方法,而在表数据网关中,您会发现 getcustomerbyId、getcustomerbyName 等。

    数据传输对象与上述两种模式不同,主要是因为它是一种分布模式,而不是上述两种模式的数据源模式。主要在您使用远程接口并且需要减少通话时使用它,因为每次通话都会变得昂贵。因此,通常设计一个可以通过线路进行序列化的 DTO,可以将所有数据传回服务器以应用进一步的业务规则或处理。

    我不精通存储库模式,因为直到现在我还没有机会使用,但会查看其他答案。

    于 2009-04-30T00:03:33.047 回答
    3

    以下只是我的理解。

    TableGateWay/RowDataGateWay:在这种情况下,网关是指一个特定的实现,它具有每个“域对象”映射到每个“域对象网关”。例如,如果我们有Person,那么我们将有一个PersonGateway来将域对象 Person 存储到数据库中。如果我们有 Person、Employee、Customer 等,我们将有 PersonGateway、EmployeeGateway 和 CustomerGateway。每个网关都会对该对象具有特定的 CRUD 功能,并且与其他网关无关。这里没有可重用的代码/模块。网关可以进一步分为 RowDataGateway 或 TableGateway,取决于您传递的是“id”还是“object”。网关通常与活动记录进行比较。它将您的域模型与数据库模式联系起来。

    Repository/DataMapper/DAO:它们是一样的。它们都指将数据库实体传输到域模型的持久层。与网关不同,Repository/DataMapper/DAO 隐藏了实现。你不知道Person后面是否有PersonGateway。它可能会,也可能不会,你不在乎。您所知道的是它必须为每个域对象支持 CRUD 操作。它将数据源和域模型解耦。

    于 2018-04-13T18:35:51.230 回答