这直接来自Zend快速入门指南。我的问题是:当setDbTable()
方法分配默认getDbTable()
对象时,为什么需要Zend_Db_Table
方法?如果您知道此映射器使用特定表,为什么甚至可能通过setDbTable()
使用“错误”表?如果代码的其余部分(find()
,fetchAll()
等)特定于Guestbook
,则能够设置表格会获得什么灵活性?
class Application_Model_GuestbookMapper
{
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Guestbook');
}
return $this->_dbTable;
}
... GUESTBOOK SPECIFIC CODE ...
}
class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
protected $_name = 'guestbook_table';
}
答案 0 :(得分:3)
Phil是正确的,这被称为lazy-loading design pattern。我刚刚在最近的一个项目中实现了这种模式,因为有以下好处:
当我调用getMember()方法时,无论之前是否设置过,我都会得到一个返回值。这非常适合method chaining:$this->getCar()->getTires()->getSize();
此模式提供了灵活性,外部调用代码仍然可以设置成员值:$myClass->setCar(new Car());
- 编辑 -
实现延迟加载设计模式时要小心。如果您的对象没有适当的水合,则会针对不可用的每个数据发出查询。最好的办法是在开发阶段拖尾数据库查询日志,以确保查询的数量和类型符合您的预期。我正在处理的一个项目是针对“详细”页面发出超过27个查询,直到我看到这些查询后我才知道。
答案 1 :(得分:1)
此方法称为延迟加载。除非先前设置,否则它允许属性在请求之前保持为空。
setDbTable()
的一个用途是进行测试。这样你可以设置一个模拟数据库表或类似的东西。
答案 2 :(得分:0)
一个补充:如果setDbTable()
仅用于延迟加载,那么将其设为私有更不合理吗?这样就可以避免意外分配和Sam最初提到的错误表格。
我们是否应该为了可测试性而牺牲设计?