模型部分的PHP设计模式[PHP Zend Framework]

问题描述 投票:0回答:3

我有一个使用Zend Framework的PHP MVC应用程序。如快速入门中所述,我在模型部分使用了3层:

  • 模型(业务逻辑)
  • 数据映射器
  • 表数据网关(或数据访问对象,即每个SQL表一个类)

该模型是​​UML设计的,完全独立于DB。

我的问题是:我不能有多个相同“实例/记录”的实例。

例如:例如,如果我获得id = 5的用户“ Chuck Norris”,这将创建一个新的模型实例,其成员将由数据映射器填充(数据映射器查询查询数据库的表数据网关)。然后,如果我将名称更改为“ Duck Norras”,则不要立即将其保存在数据库中,而是将同一用户重新加载到另一个变量中,那么我将遇到“同步”问题...(<记录”)

现在,我使用

Multiton / Identity Map模式:像Singleton一样,但是多个实例由一个键索引(在我们的示例中为用户ID)。但这使我的发展非常复杂,我的测试也变得很复杂。

如何正确处理?

php design-patterns zend-framework oop
3个回答
0
投票
将所有已加载的模型实例保留在“实时模型池”中。当您加载/查询模型时,首先检查它是否已经加载到池中(使用主键或类似概念)。如果是这样,则从池中返回对象(或引用)。这样,您所有的引用都指向同一个对象。我的术语可能不正确,但希望您能理解。基本上,池充当业务逻辑和数据库之间的缓存。

1
投票
Identity Map

编辑

针对此评论:

如果我有“从X中选择*”,如何跳过获取已加载的记录?

您不能在查询本身中,但是可以在将行加载到实体对象中的逻辑中。用伪代码:

class Person {} class PersonMapper { protected $identity_map = array(); function load($row) { if (!isset($this->identity_map[$row['id']])) { $person = new Person(); foreach ($row as $key => $value) { $person->$key = $value; } $this->identity_map[$row['id']] = $person; } return $this->identity_map[$row['id']]; } } class MappingIterator { function __construct($resultset, $mapper) { $this->resultset = $resultset; $this->mapper = $mapper; } function next() { $row = next($this->resultset); if ($row) { return $this->mapper->load($row); } } }

实际上,您可能希望MappingIterator实现Iterator,但为了简洁起见,我跳过了它。

0
投票
Multiton

最佳选项,如果您想在项目中使用各种单例。

Iterator
© www.soinside.com 2019 - 2024. All rights reserved.