2012-10-26 39 views
2

減輕的一個具體方面:
Factory Pattern. When to use factory methods?使用工廠獲取特定對象的優勢?

在我的團隊有一個關於工廠設計模式的討論。

在我們的項目,我們有一些工廠正在建造像這樣的:

class ProductFactory { 

    const PRODUCT_A = 'product_a'; 
    const PRODUCT_B = 'product_b'; 
    const PRODUCT_C = 'product_c'; 

    private static $classMapping = array(self::PRODUCT_A => 'A', 
             self::PRODUCT_B => 'B', 
             self::PRODUCT_C => 'C'); 

    public function create($productConstant) { 
     $className = self::$classMapping[$productConstant]; 
     return new $className(); 
    } 
} 

的討論是關於使用這個工廠。 如果我從來沒有動態地定義產品,並且始終定義我喜歡從中收回的產品,是否有任何需要使用此模式?

+0

您可以稍後更改具體的產品,而不會更改太多的代碼。 – hakre

+0

只是在一面注意:如果我沒有完全錯誤,你不會實例化ProductFactory。因此,它需要創建一個靜態方法('public static function create()')。 – ExternalUse

+3

@ExternalUse:請不要暗示。謝謝!您稍後想要替換工廠(例如,用於測試系統),然後靜態殺死所有這些。毋容。如果你對自己的判斷是公平的,你就不會建議一個全球性的功能,會有嗎? – hakre

回答

2

工廠的優勢是它們可以分離代碼。把你的Foo類,它需要的A一個實例:

class Foo { 

    public function __construct() { 
     $a = new A; 
    } 

} 

Foo現在連接到的類A,因爲它在硬編碼的源類名。如果您想要,您不能提供AFoo的替代實現,例如在測試中模擬A。這裏就是工廠進來:

class Foo { 

    public function __construct(ProductFactory $factory) { 
     $a = $factory->create($factory::PRODUCT_A); 
    } 

} 

在需要時您現在可以注入任何種類的AFoo,你已經分離了兩個班。

這就是工廠的用途。適當時使用它們。如果耦合FooA沒有問題,給您更多的權力。

+0

如果您使用依賴注入來注入工廠,但仍然傳遞$ factory :: PRODUCT_A,那麼您並不真正解耦任何事情......您只是在改變A得到實例化的方式,爲了使其有效,成爲某種機制來確定需要實例化的產品。這是我的樂趣,有興趣聽到你的想法 – frosty

+0

@frosty爲什麼?你可以傳遞一個完全不同的'$ factory',當用'create($ factory :: PRODUCT_A)'調用時,它返回一個完全不同的對象。該常數/參數並不排除多態性。你所需要做的只是'ProductFactory'的子類,並改變'private static $ classMapping'中的值。 – deceze

+0

是的,這是有道理的,我同意。我想你正試圖解決的問題將決定你需要做什麼。正如你所提到的,「如果將Foo耦合到A沒有問題」 – frosty

1

這取決於。

設計模式可以解決問題,而不會產生問題。

  • 如果您要在另一個類中創建產品,工廠可以提供一個模擬對象進行測試。
  • 如果您要爲構造函數創建具有不同類型數據的產品,工廠將派上用場。
  • 如果你會嚴格使用依賴注入,你不需要工廠
  • 如果工廠沒有真正的理由,不要使用一個。