2011-09-27 32 views
3

如果我有一個相當複雜的用戶模型,我想使用數據映射模式來加載,我怎麼會懶惰地加載用戶信息的一些更密集的位而不允許用戶知道UserMapper?例如 - 如果用戶模型允許一個Address對象數組(並且用戶可能有很多這樣的對象,但不一定需要事先提供),那麼如果/需要時我將如何加載這些對象?如何使用Data Mapper模式懶惰地加載子對象?

我是否讓用戶模型知道AddressMapper?

我是否將用戶模型BACK傳遞到UserMapper中,然後只保存地址?

有更好的選擇嗎?

回答

7

嗯,我一次發現了以下聰明模式,Ben Scholzen,Zend Framework的開發者。它是這樣的:

class ModelRelation 
    implements IteratorAggregate 
{ 
    protected $_iterator; 
    protected $_mapper; 
    protected $_method; 
    protected $_arguments; 

    public function __construct(MapperAbstract $mapper, $method, array $arguments = array()) 
    { 
     $this->_mapper = $mapper; 
     $this->_method = $method; 
     $this->_arguments = $arguments; 
    } 

    public function getIterator() 
    { 
     if($this->_iterator === null) 
     { 
      $this->_iterator = call_user_func_array(array($this->_mapper, $this->_method), $this->_arguments); 
     } 

     return $this->_iterator; 
    } 

    public function __call($name, array $arguments) 
    {   
     return call_user_func_array(array($this->getIterator(), $name), $arguments); 
    } 
} 

本Scholzen的實際執行is here

你會使用它的方式,是這樣的:

class UserMapper 
    extends MapperAbstract 
{ 
    protected $_addressMapper; 

    public function __construct(AddressMapper $addressMapper) 
    { 
     $this->_addressMapper = $addressMapper; 
    } 

    public function getUserById($id) 
    { 
     $userData = $this->getUserDataSomehow(); 

     $user = new User($userData); 
     $user->addresses = new ModelRelation(
      $this->_addressesMapper, 
      'getAddressesByUserId', 
      array($id) 
     ); 

     return $user; 
    } 
} 

class AddressMapper 
    extends MapperAbstract 
{ 
    public function getAddressesByUserId($id) 
    { 
     $addressData = $this->getAddressDataSomehow(); 

     $addresses = new SomeAddressIterator($addressData); 

     return $addresses; 
    } 
} 

$user = $userMapper->getUserById(3); 
foreach($user->addresses as $address) // calls getIterator() of ModelRelation 
{ 
    // whatever 
} 

的事情是,雖然;如果對象圖變得非常複雜並且在某個時刻深度嵌套,這可能會變得非常緩慢,因爲映射器都必須查詢他們自己的數據(假設您正在使用數據庫來實現持久性)。當我使用此模式獲取嵌套的對象(任意深度的子頁面)時,我遇到過這種情況。

它可能會調整一些緩存機制,以加快事情雖然。