1

我在我正在开发的 PHP 应用程序中使用数据映射器模式并且有一个问题。目前,您请求一个具有特定 ID 的 Site 对象,映射器将查找该行,创建一个对象并返回它。但是,如果您对同一个站点再次执行此操作,您最终会得到两个具有相同数据的不同对象。例如。:

$mapper = new Site_Mapper();
$a = $mapper->get(1);
$b = $mapper->get(1);

$a == $b // true
$a === $b // false

所以,我的问题是,我应该:

  1. 将实例化的 Site 对象存储在映射器中,这样我就可以在创建新对象之前检查它们是否已经存在(如果有多个相同类型的映射器可能会出现问题)
  2. 执行与 #1 相同的操作,但确保每个映射器只有一个实例
  3. 与 #1 一样,但使用静态属性,因此多个实例不是问题
  4. 不要担心,因为它 可能不是问题
4

3 回答 3

5

您正在寻找的是身份映射模式。不过要小心所谓的“阅读不一致”。当您使用“旧实例”时,数据库可能已经更改。当你编辑你的对象时,另一个用户可能会得到它的一个实例,更快地改变它并更快地保存它。然后另一个对象再次覆盖所有这些更改。在网络上,虽然可能不是一个大问题,因为“页面”很快就会通过并且没有对象存活超过几分之一秒。

于 2010-01-04T18:15:42.510 回答
2

我知道这个问题是很久以前提出的,但仍然想回答,以防万一其他人陷入类似的困境。实际上作者提出的上述建议#1,2,3都是相关的,为了解决问题,应该考虑它们。

1) 将从 DB 对象中检索到的每个存储在映射器中,以便在请求具有相同 ID 的对象时不必再次执行此操作。在所有后续调用中,映射器应返回存储的对象。这称为IdentityMap模式。为此,请在映射器中创建一个私有属性来保存给定对象类型的 IdentityMap 实例。Site_Mapper->get() 方法应该始终检查给定 ID 的 IdentityMap,如果对象没有被检索到,映射器将转到数据库,但如果它已经存储在地图中,它会返回缓存的实例,将行程保存到数据库。那么 $a === $b 应该是真的,因为它们是对同一个对象实例的引用。

2) 是的,理想情况下,应该始终存在给定数据映射器 (Site_Mapper) 的一个实例,以便在给定时间维护一个 IdentityMap 实例。这可以使用单例模式来完成。这可以通过像Site_Mapper::getInstance()这样的 getter 方法实现,它总是返回给定映射器的相同实例。您还必须将__construct()声明为私有方法,以防止使用new进行不必要的实例化,并确保getInstance()是实例化映射器的唯一方法。

3)作者上面提到的关于静态属性的内容也是正确的。要在 PHP 中实现Singleton,必须使用静态属性来保存 Mapper 的实例。

我强烈推荐 Martin Fowler 的《企业应用程序架构模式》一书,其中讨论了上述模式等等。这是一本很好的读物,尤其是如果您正在开发自己的自定义 ORM 解决方案。希望有帮助。

于 2010-09-20T05:17:58.680 回答
1

我会以某种方式进行缓存 - 静态映射器类将是我的第一选择,也是我见过的最多的。否则,您的选项 2(这是单例模式)可能是最好的选择。

请记住,您需要在进行更新时清除此缓存以避免返回过时的数据。

话虽如此,除非您正在制作一些东西来获得大量使用或进行大量查询,否则这可能无关紧要。(你的 4 个)

也值得看一下指导(我相信有很多例子,我最了解这个),Propel(http://propel.phpdb.org/)具有缓存功能 - 可能值得看看它是如何做的它?或者只是使用它?

于 2009-01-31T18:15:51.010 回答