数据映射器、表数据网关(Gateway)、数据访问对象(DAO)和存储库模式之间有什么区别?

2024-01-03

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

除了命名约定(例如 CustomerMapper、CustomerDAO、CustomerGateway 和 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);

对于数据映射器和存储库模式来说,这似乎是相同的原理; DAO 模式(我认为这与网关是同一回事?)似乎也鼓励特定于数据库的网关。

我错过了什么吗?使用 3-4 种不同的方法来做同一件事似乎有点奇怪。


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

A 存储库 “除了具有更精细的查询功能外,其行为就像一个集合” [埃文斯,领域驱动设计 https://web.archive.org/web/20210507021346/http://domaindrivendesign.org/books/evans_2003] 并可被视为“内存外观中的对象” (存储库讨论 https://web.archive.org/web/20210126033021/http://geekswithblogs.net/gyoung/archive/2006/05/03/77171.aspx)

A 数据映射器 “在对象和数据库之间移动数据,同时保持它们彼此独立以及映射器本身独立” (福勒、PoEAA、制图员 https://martinfowler.com/eaaCatalog/dataMapper.html)

A 表数据网关 is “一个数据库表的网关(封装对外部系统或资源的访问的对象)。一个实例处理表中的所有行" (福勒、PoEAA、TableDataGateway https://martinfowler.com/eaaCatalog/tableDataGateway.html)

A DAO “将数据资源的客户端接口与其数据访问机制分开/将特定数据资源的访问 API 调整为通用客户端接口”允许“数据访问机制的更改独立于使用数据的代码” (太阳蓝图 https://www.oracle.com/java/technologies/data-access-object.html)

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据映射器、表数据网关(Gateway)、数据访问对象(DAO)和存储库模式之间有什么区别? 的相关文章

随机推荐

  • 如何更改 IntelliJ 中所有模块的语言级别

    我有一个包含许多模块的项目 我们正在升级到 Java7 我希望我的编辑器能够反映这一点 现在我的所有模块都专门将语言级别设置为Java6 并且模块太多 我无法为每个模块更改此设置 如何将所有模块设置为 Java7 更好的是 如何设置所有模块
  • SharedPreferences 替换数据

    我有一个应用程序 每当我按下按钮时都会给我一些字符串 然后使用共享首选项保存该值 但是 我想限制此保存功能 因此它只会保存最后三个收到的字符串 其结构如下 字符串A 字符串 B 字符串 C 下次当我单击按钮时 它将将该值记录到字符串 A 中
  • Python:如何从列表中检查字符串中的子字符串? [复制]

    这个问题在这里已经有答案了 如何检查字符串中列表中包含的子字符串 例如检查字符串是否包含 字符串 列表中的元素 https stackoverflow com questions 500925 但是在 Python 中呢 试试这个测试 an
  • Lambda 表达式的代码覆盖率

    我在整个代码中看到一种模式 其中 lambda 表达式显示为未包含在代码覆盖范围内 调试器确实单步执行代码并且没有条件块 public CollectionModel List
  • Ocaml 变体类型

    无论我读什么教程 手册 OCaml 类型总是让我感到困惑 我需要定义一个类型 比如说测试 它包含以下形式 具有以下形式之一的类型 a b 测试 空 T t N n Seq x1 xn 我知道如何做前 3 个 但我完全不知道如何定义最后一个形
  • 从 git 标签获取版本(通过 pbr)

    I use pbr https pypi python org pypi pbr用于包装 它从 git 标签获取版本并将其应用于 setup py 现在我还想在包中提供可用的版本 例如有一个 version 属性 我可以使用pbr图书馆为此
  • Ionic 3:从 PlayStore 链接获取价值

    我有一个 Ionic 3 应用程序 我想根据 Playstore 的下载链接在其中设置一些变量 例如 http linktoplaystore com app account 4会将我的应用程序内的帐户变量设置为 4 有什么方法可以实现此目
  • CasperJS 将数据传回 PHP

    PHP 正在使用 CasperJS 调用exec 命令 CasperJS 完成检索网页部分内容等工作后 如何将检索到的数据返回给 PHP 我认为将数据从 CasperJS 传输到另一种语言 例如 PHP 的最佳方法是将 CasperJS 脚
  • 如何调试使用 Chrome/WebKit 作为远程调试器运行的 Node.js 服务器?

    如果你的节点正在运行 node debug server js 这给了我一个端口号 xxxx 我应该在启动 Chrome 时使用这个端口号吗 您是否从远程调试它Google Chrome remote debugging port xxxx
  • 如何测试使用 mechanize 的 ruby​​ 应用程序

    我编写了一个使用 Mechanize 遍历站点的小程序 我想为它编写测试 但不希望它在每次运行测试时都实际登录到该网站 我想模拟互联网 以便当它访问某个站点时 它只是返回存储的结果 这是一个小例子 假设我的代码的目的是从谷歌主页上提取链接
  • 如何制作表格超链接的单元格

    在没有 javascript 或 jquery 的情况下 如何在 html 中对整个表格单元格进行超链接 我尝试将 href 放入 td 标签本身 但至少在 chrome 18 中不起作用 td href http www m w com
  • 使用正则表达式排除某些字符

    尽我所能 我无法让正则表达式排除空格或单引号 允许使用字符串 abc 不允许 a bc abc abc 等 上例中的空格也可以替换 假定已删除尾随和前导空格 其他地方检查空字符串 目标语言是javascript 如果我使用 SQL 我会使用
  • Laravel - 雄辩的“Has”、“With”、“WhereHas” - 它们是什么意思?

    我发现这些方法背后的概念和含义有点令人困惑 有人可以向我解释一下它们之间的区别吗 has and with是 在一个例子的上下文中 如果可能的话 With with is for 急切加载 这基本上意味着 Laravel 将沿着主模型预加载
  • Facebook Graph 高分辨率照片

    我正在为 me home 执行 Facebook Graph API 调用 以获取用户的新闻源 众所周知 您在 图片 字段中获得的 URL 是低分辨率照片 在 100x100 以上的分辨率下看起来效果不佳 我知道您可以通过对 object
  • Swift:无法预加载 Coredata

    当我在 目标 构建阶段 复制捆绑资源 下包含带有 Objective C 的 SQLite 文件时 该文件将被完全复制到目标 即设备或模拟器 在目标上 我得到整个文件 表和内容 记录 行 对 Swift 进行同样的操作 表将被复制 但它们是
  • Flexslider无限循环不起作用

    我在网上到处找 Flexslider 有一个众所周知的问题 无论是滑块还是轮播 当它到达滑块中的最后一个项目时 它会飞回第一个项目 而不是保持无限循环平滑 我不敢相信没有人能解决这个问题 这是我正在使用的 flexSlider 代码 doc
  • 是什么原因导致 ClassCastException: java.util.TreeSet 无法转换为 java.lang.Comparable?

    因此 我尝试将一定长度的所有字符串从字符串集合 可以是集合或列表 移动到 TreeMap 并将每个字符串中的字符集设置为该字符串的键 但这条线map put keyRinger word word throws java lang Clas
  • 以下reinterpret_cast是否会导致未定义的行为?

    是否reinterpret cast下面的代码中会导致未定义的行为吗 如果确实如此 是否可以定义rpd以类型安全的方式 class Base public virtual Base default class Derived public
  • OAuth 回调 URL 与 nginx 代理服务器行为不兼容

    在过去的三天里 我花了很大一部分时间尝试互联网上的每一个解决方案 但感到绝望 这是问题陈述 我有一个包含三个服务的 Dockerized 应用程序 带有gunicorn的django应用程序 web Nginx 服务器 nginx Post
  • 数据映射器、表数据网关(Gateway)、数据访问对象(DAO)和存储库模式之间有什么区别?

    我正在尝试温习我的设计模式技能 我很好奇这些模式之间有什么区别 所有这些看起来都是同一件事 封装特定实体的数据库逻辑 因此调用代码不了解底层持久层 根据我的简短研究 它们通常都实现标准 CRUD 方法并抽象出特定于数据库的细节 除了命名约定