2010-08-05 46 views
1

那麼,工廠模式是否合適?

我有一個問題(好吧,沒有真正的問題,但我想嘗試一些新的東西)與創建對象。其實我有一些訂單,其中包含一個訂購項目列表。

這些訂單項已在整個應用程序中使用,因此我需要一種方法來創建它們。主要的問題是,我希望能夠以許多不同的方式創建這些對象。

其實我在類的構造函數中執行此操作,並檢查給定的參數。 (我使用PHP,所以從你一定會知道:)語言沒有超載支持)

一個簡單而快速的例子

class foo { 
    protected $_data=null; 
    public function __contruct($bar){ 
     if (is_array($bar)){ 
      $this->_data=$bar; 
     } 
     else { 
      $dataFromDb=getDataFromDatabase 
      $this->_data=$dataFromDb; 
     } 
    } 
} 

無論如何,如果我想創建我的對象給出另一種類型的參數,可以說一個封裝在字符串中的xml文檔,我需要將所有這些東西放在我的構造函數中。 如果創建對象的過程更復雜,我最終需要爲每種類型創建一個單獨的方法,我想啓動。但是隻有在創建這種特殊類型時纔會調用此方法。 (我認爲你有問題:))

另一個問題想到,如果我需要在構造函數中創建具體對象的更多參數,我修改了所有我的代碼,導致構造器改變。 (好吧,我可以給他更多的參數並使用默認值,但這不是我真正想要的)。

所以我的問題是,哪種模式適合這個問題來解決我創建一個具體的對象。我想爲每一種我想要創建具體對象的方式創建一個工廠。但我不確定這是否是解決此類問題的常見解決方案。

回答

2

IF改變我會做它像這樣(一拉Zend框架的通用構造函數)的構造其唯一的簽名:

class foo { 
    // params 

    public function __construct($options = null) 
    { 

    if(null !== $options) 
    { 
     $this->setOptions($options); 
    } 
    } 

    public function setOptions(array $options){ 

    foreach ($options as $name => $value){ 
     $method = 'set' . $name; 
     if(method_exists($this, $method) 
     { 
     $this->$method($value); 
     } 
    } 

    return $this; 
    } 
} 

這essntially意味着所有構造函數參數數組元素與名爲鍵,以及在初始化過程中你想要在這個數組中使用的任何東西,你創建一個setter,然後自動調用它。缺點是在IDE中缺乏有效的暗示。

。如果您想擁有特定的構造函數的話,我可能會用一個工廠去,但仍是otherhand使用大致相同的方法:

class foo { 

    public static function create($class, $options) 
    { 
    if(class_exists($class)) 
    { 
     $obj = new $class($options); 
    } 
    } 
} 

當然,你可以選擇使用PHP的反射來確定如何調用構造函數而不是僅僅注入任意數組參數。

+0

哇,例如一個代碼是非常好的。花了我一段時間來理解它,但我會明確地使用它,如果它匹配我得到的任何問題。 但在具體的情況下,我認爲你的第二個例子是我想要這樣做的方式。 所以我創建了一個我當前的抽象基類,並在每個我想要創建對象的方式中執行分離類中的具體事情。 謝謝你,你的例子真的讓我很開心。 – evildead 2010-08-05 22:44:19

+0

很高興幫助...請不要我改變構造函數一點...我很早就着急了:-) – prodigitalson 2010-08-05 23:25:23

+0

我瞎了,什麼改變了? – evildead 2010-08-05 23:36:48

1

你可以簡單地使它與可選PARAMS工廠:)

class Example_Factory 
{ 
    public static function factory($mandatoryParam, $optionalParam = null) 
    { 
     $instance = new self; 
     $instance->setMandatory($mandatoryParam); 

     if ($optionalParam !== null) { 

      $instance->setOptional($optionalParam); 
     } 

     return $instance; 
    } 

    public function setMandatory($in) 
    { 
     // do something.... 
    } 

    public function setOptional($in) 
    { 
     // do some more... 
    } 
} 
+0

也非常感謝你的回答。這也是一個很好的解決方案,但我認爲我不能適應我的具體問題,因爲我沒有強制性和可選的東西。我賦予我的具體構造函數的值不能分成這兩類。 – evildead 2010-08-05 22:49:28

+0

好吧,它不是強制性的/可選的,它只是一個例子,你也可以只有一個參數或5.模式是根據輸入數據調用新實例的方法:) – 2010-08-05 23:06:17