2012-11-12 31 views
1

當建立一個表示一些對象狀態的列表時,我應該詢問每個 對象的狀態並自己修改列表,或者我應該給對象 列表並告訴它添加本身?建立一個基於對象狀態的列表

我正在構建頁面上輸出模板的列表。表單元素 要求將該列表蒸餾至鍵/值對。一位同事提到 ,我應該更多地關注「告訴,不要問」,並且我正在努力讓 理解這個問題的原理。

我已經採取了一種方法,我創建了TemplateList 的一個實例,然後要求每個模板將自己添加到列表中。這允許模板 確定它將傳遞給TemplateList::addTemplate()的參數。

class TemplateList { 
    public $templates = array(); 

    public function addTemplate($id, $label) { 
     $this->templates[$id] = $label; 
    } 

    public function getTemplates() { 
     return $templates; 
    } 
} 

interface TemplateInterface { 
    public function addToTemplateList(&$templatelist); 
} 

class DiskTemplate implements TemplateInterface { 
    public function addToTemplateList(&$template_list) { 
     $template_list->addTemplate($this->name, $this->name); 
    } 
} 

class DatabaseTemplate implements TemplateInterface { 
    public function addToTemplateList(&$template_list) { 
     $template_list->addTemplate($this->id, $this->name); 
    } 
} 

使用範例:

$template_list = new TemplateList; 

// fetch $disk_templates and $db_templates 

foreach ($disk_templates as $template) { 
    $template->addToTemplateList($template_list); 
} 

foreach ($db_templates as $template) { 
    $template->addToTemplateList($template_list); 
} 

另一種方法是要求模板用於它的狀態和結果添加到模板列表:

$template_list = new TemplateList; 

// fetch $template 

$template_list->addTemplate($template->propertiesForTemplateList()); 

是否有優勢,這兩種方法?還有什麼我完全沒有考慮到的?

回答

1

首先在原理上有一個小錯誤:其「Tell, don't ask」:)。你可以找到關於這個和其他原理的非常好的文章here。基本思想是,不要向對象提問,然後決定要做什麼,而應該告訴對象要做什麼。每個對象(例如,基於其內部狀態)應該知道如何處理任務(消息發送)。 這對於保持良好分配的職責非常重要。如果你向某個對象提問,但決定在另一個對象中做什麼,那麼你將一個對象的內在邏輯分解爲許多對象。這會產生難以測試和維護的代碼,因爲您沒有內聚對象和單個位置來修改/測試功能。 這裏出現的第二個問題是封裝;在大多數情況下,對象的狀態是私有的,人們將其公開,以便可以查詢對象的狀態以便稍後執行操作。根據一般經驗,我認爲這是一種氣味,因爲你(再次)不僅將對象責任傳播給系統的其他部分,而且還違反對象的封裝。請注意,我並不是在說吸氣劑本身就是壞的,只是如果你需要公開你的狀態以便其他物體可以爲你做出決定,你可能會走錯路。

現在,轉到您的代碼,我認爲第一種方法是完全有效的,因爲它是知道如何將自身添加到列表以及應該使用哪些屬性的對象。如果有必要,您將保持良好的責任分配和內部狀態封裝。

HTH

+0

哈,哎呦。我有一個標籤中的「告訴,不要問」文章,只是改變了文字。固定。感謝您的答覆。 –

+0

不客氣。如果你可以閱讀奈特的文章;它不僅具有我閱讀過的關於OO設計的最好建議,而且它也很容易閱讀。 –

相關問題