Zend - 设计模式DataMapper&表网关

时间:2012-02-09 20:05:26

标签: zend-framework design-patterns

这直接来自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';
}

3 个答案:

答案 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最初提到的错误表格。 我们是否应该为了可测试性而牺牲设计?