2011-08-08 48 views
25

我以前一直和各種ORM一起工作,並將我所有的邏輯放在模型中,而不管它是什麼性質--SQL,MongoDB查詢&甚至讀取遠程JSON對象。 但是,當需要確保鬆耦合以提高可測試性時,這種方法的問題會很快出現。瞭解域對象+數據映射器模式?

今天我已閱讀關於將模型分爲兩部分,Domain objects & Data mappers
如果我完全理解它,Domain objects完全不知道使用的存儲,而是存在處理業務邏輯。另一方面,Data mappers負責將設置在Domain objects中的數據存儲到設定的數據存儲器中。

但是,我發現在網上找到一個很好的,易於理解的示例很難找到如何在現實世界的示例中使用DomainObjects DataMapper。

請問這個(下面顯示的代碼)是否與我的代碼中的DomainObjects & DataMappers一起使用來存儲用戶或我的頭腦中都弄錯了嗎?

$user = new User_DO; 
$userSave = new User_DM; 
$userSave->store($user->add(array('name' => 'John Doe'))); 

class User_DO { 

    function add($array) { 
     if(!isset($array['name'])) { 
      throw new Exception("Name must be set"); 
     } 

     return $array; 

    } 

} 

class User_DM { 

    function store($array) { 
     MyDatabase::execute("INSERT INTO..."); 
    } 

} 
+0

在現實世界中可能是一個愚蠢的例子,但它可以更好地解釋模式,它將是一個帶有「年齡」字段的域對象,而數據映射器會保留「年份」值。 –

回答

24

這個想法背後是有一個標準的對象,代表現實生活中的當前狀態或換句話說,在域中。這個域模型通常是一個沒有邏輯的數據集合。

class person_DO { 
    public $id; 
    public $firstname; 
    public $lastname; 
    public $addresses; 
} 

此域模型的實例的裝載(域對象)和持久性是通過數據映射器處理 - 例如上述人的地址可以通過1位於另一個表:N的關係,因爲這樣的:

TABLE person { 
    id  INTEGER PRIMARY KEY, 
    firstname VARCHAR(32), 
    lastname VARCHAR(32) 
} 

TABLE addresses { 
    id INTEGER PRIMARY KEY, 
    person_id INTEGER FOREIGN KEY ON person.id, --Reference on person-row 
    street  VARCHAR(64), 
    ... 
} 

的person_DO並不需要知道這些,但DataMapper的呢,因爲它聚集了持續期間加載和分離過程中的數據:

class person_DM { 
    /** 
    * @param [integer] $id 
    * @return [person_DO] an instance of a person or null, if no person 
    *      with that id was found. 
    */ 
    public function findById ($id) {...} 

    /** 
    * @return [array of person_DO] 
    */ 
    public function fetchAll() {...} 

    /** 
    * persists a person object 
    * @param [person_DO] an instance of a person 
    */ 
    public function saveOrUpdate(person_DO $person) {...} 
} 

爲了更解耦不同地方,DataMappers通常使用DBTABLE網關或類似的圖案,以允許使用不同的數據庫或類似動作。這樣,我可以有幾個具有相同模式的數據庫,但例如在不同的組織中用相同的代碼構建數據倉庫,只有不同的數據庫對象。

作爲一個實際的例子,我會建議看看Zend Framework的Quickstart Tutorial,這正是我剛纔簡要解釋的。

+0

映射器如何處理具有雙邊多對多關係的域?說這個人_DO有多少address_DO或什麼的。如果你想改變這個人的地址,你會在域中改變它,然後把它留給映射器來堅持person_DO擁有的新關係?或者你會使用映射器來更改數據庫記錄,從而更新域...? – user965369

+1

「此域模型通常是沒有邏輯的數據集合。」 我不認爲這個陳述必然是準確的。你的域對象應該代表狀態+行爲(業務邏輯)。你不希望他們做的是包含持久性邏輯。 – AgmLauncher

+2

「此域模型通常是沒有邏輯的數據集合。」這根本不準確。這是一個貧血模型和小窮人,你的領域邏輯應該在你的領域對象內,這是簡單的封裝。 – Andrew

8

近似的方式,是。雖然我會強烈建議不要重新發明車輪,並使用一個複雜的ORM,如Doctrine 2.x來實現這種模式。您可以查看他們的文檔(Chapter 8: Working with objects)以對接口進行採樣。