2009-10-05 97 views

回答

12

雖然這並不一定是它的主要用途,這是很好的東西,你有專門的一個類的實例:

public ITax BuildNewSalesTax() 
public ITax BuildNewValueAddedTax() 

您需要兩種方法來建立一個徵稅對象,但你不想每次都必須依賴於使用「新」,因爲構造函數可能很複雜。通過這種方式,我可以將所有更改封裝到單個方法中,以供其他人在未來進行維護時使用。

31

我有兩種情況下,我傾向於使用它:

  1. 需要以某種特定方式要被初始化的對象
  2. 當我想構造基於抽象類型的特定類型(一個抽象類或接口)。

例子:

  1. 第一種情況可能是你想擁有一個工廠創建SqlCommand對象,在那裏你會自動返回命令對象之前附上有效SqlConnection

  2. 第二種情況是如果您有一個接口定義並確定在執行時使用哪個接口的確切實現(例如通過在配置文件中指定它)。

0

向你從我的觀點問題答案的第二部分,我認爲這是比「新」關鍵字更好的原因是工廠方法減少了對特定類的構造函數的扶養。通過使用工廠方法,可以將有問題的對象的創建委派給其他人,因此調用者不需要了解如何創建對象。

20

您可以參考框架設計指南第2版第9.5節「工廠」。下面是引用對於一套指引,使用工廠在構造函數:

DO喜歡構造函數來 工廠,因爲他們通常 更多可用的,一致的, 比專業 建設機制方便。

考慮使用一個工廠,如果你需要更多的 比的控制可以通過 構造了創建 實例來提供。

DO使用的情況下,其中一個 顯影劑可能不知道來構造該類型 ,工廠這樣的編碼 針對基類型或接口時。

考慮使用工廠如果有 命名方法是使 操作不言自明的唯一方法。

DO使用工廠轉換式 操作。

並從第5節開始。3構造設計

考慮使用構造的靜態工廠方法代替,如果所需要的操作的 語義,或者如果下面的構造設計指導 不直接映射到建築 重刑一個新的實例感覺不自然。

0

最好有一個工廠方法模式與新的關鍵字。這個想法是移動業務邏輯之外的對象的完整實例化。這個原則是dependency injection的癥結所在。而且,工廠方法的工作可以在稍後的時間委託給Spring.net或Castle Windsor之類的依賴注入框架。

+1

我在每一個「新」與工廠的代表,充分的IoC Containered更換一個代碼庫工作。與之合作是一場噩夢。經過一年半的開發與5個開發人員,它被廢棄。 3個開發者使用行業標準做法在1個月內取代了功能。根據我的經驗,工廠在@Dzmitri指出的情況下非常有用。除非你打算通過配置來切換類型,或者有非常有趣的構造函數邏輯,否則我認爲用工廠替換新的方法是過分的,並且適得其反。 – Fred 2016-04-05 15:27:57

1

當系統應該獨立於其產品的創建,組成和表示方式時,使用抽象工廠模式。 系統應該配置多個產品系列之一。 相關產品對象系列旨在一起使用,並且您需要強制執行此約束。 你想提供一個產品類庫,並且你只想揭示它們的接口,而不是它們的實現。

-1

我想它是什麼時候你希望你的應用程序在未經編碼改變的情況下在未來是鬆散耦合和可擴展的。

我在博客上寫了一篇文章,爲什麼我在我的項目中選擇工廠模式,可能會給你更多的見解。這個例子是在PHP中,但我認爲它通常適用於所有語言。

http://www.mixedwaves.com/2009/02/implementing-factory-design-pattern/

5

我使用出廠時圖紋

  1. 當一個類不知道它必須創造哪些對象的類。

  2. 一個類指定了它的子類來指定要創建的對象。

  3. 在程序員的語言(非常原始的形式)中,您可以使用工廠模式,您必須根據提供的數據創建任何一個子類的對象。

24

,當你想用不同的組件重用常用功能使用工廠方法(不是抽象工廠)。

例:想象一下,你有一個M16步槍。像這樣的:

public class M16 
{ 
    private Scope scope = new StandardScope(); 
    private SecondaryWeapon secondary = new Bayonet(); 
    private Camouflage camo = new DesertCamo(); 

    public double getMass() 
    { 
     // Add the mass of the gun to the mass of all the attachments. 
    } 

    public Point2D shootAtTarget(Point2D targetPosition) 
    { 
     // Very complicated calculation taking account of lots of variables such as 
     // scope accuracy and gun weight. 
    } 
} 

你可能會滿意它一段時間,認爲你不會想改變任何東西。但是那時你必須在叢林中進行祕密的夜間隱形任務,並且你意識到你的依戀完全不合適。你真的需要一個NightVision示波器,JungleCamo和一個GrenadeLauncher輔助武器。你將不得不從原來的M16複製過來的代碼......不夠好的可擴展性.....工廠方法來拯救!

重寫你的M16類:

public abstract class M16 
{ 
    private Scope scope = getScope(); 
    private SecondaryWeapon secondary = getSecondaryWeapon(); 
    private Camouflage camo = getCamouflage(); 

    public double getMass() 
    { 
     // Add the mass of the gun to the mass of all the attachments. 
    } 

    public Point2D shootAtTarget(Point2D targetPosition) 
    { 
     // Very complicated calculation taking account of lots of variables such as 
     // scope accuracy and gun weight. 
    } 

    // Don't have to be abstract if you want to have defaults. 
    protected abstract Scope getScope(); 
    protected abstract SecondaryWeapon getSecondaryWeapon(); 
    protected abstract Camouflage getCamouflage(); 
} 


//Then, your new JungleM16 can be created with hardly any effort (and importantly, no code //copying): 

public class JungleM16 : M16 
{ 
    public Scope getScope() 
    { 
     return new NightVisionScope(); 
    } 

    public SecondaryWeapon getSecondaryWeapon() 
    { 
     return new GrenadeLauncher(); 
    } 

    public Camouflage getCamouflage() 
    { 
     return new JungleCamo(); 
    } 
} 

主要的想法?在保留常用功能的同時自定義和交換合成對象。

實際有用的地方使用它: 你剛剛設計了一個很酷的圖形用戶界面,而且它有一個非常複雜的佈局。如果你想擁有不同的小部件,那麼再次佈置所有東西將是一件非常痛苦的事情。所以......使用工廠方法來創建小部件。然後,如果您改變了主意(或者其他人想要使用您的類,但使用不同的組件),那麼您可以繼承GUI的子類並覆蓋工廠方法。

+2

嘿它的一個很好的解釋,你寫了任何教程,我愛愛讀它們..! – 2012-03-25 19:22:31

+1

嘿,好的解釋。它使理解起來更容易。做得好。 – Flavio 2017-07-02 11:29:28

0

工廠模式與對象的實例化比不暴露實例化邏輯。換句話說,Factory實際上是具有通用接口的對象的創建者。

它讓子類來決定實例化哪一個類。

請看下面的例子:

namespace TestApp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //Store is ordering the factory to get office shoes 
      Shoe shoe = ShoeFactory.GetShoes("OFFICE"); 
      Console.WriteLine(shoe.GetType()); //Will be office shoes 

      //Store is ordering the factory to get sports shoes 
      shoe = ShoeFactory.GetShoes("SPORTS"); 
      Console.WriteLine(shoe.GetType()); //Will be sports shoes 
     } 
    } 

    //This is the factory supplying shoes. It can supply sports shoes or office shoes 
    //based on demand 
    class ShoeFactory 
    { 
     public static Shoe GetShoes(string strShoeType) 
     { 
      switch (strShoeType) 
      { 
       case "SPORTS": return new SportShoe(); 
        break; 
       case "OFFICE": return new OfficeShoe(); 
        break; 
       default: 
        return null; 
      } 
     } 
    } 

    //This is an abstract class representing product family 
    //In this example, its shoe 
    public abstract class Shoe 
    { 

    } 

    //Office shoe is a concrete class belongs to shoe family 
    class OfficeShoe : Shoe 
    { 

    } 

    //Sports shoe is a concrete class belongs to shoe family 
    class SportShoe : Shoe 
    { 

    } 
} 
+0

但是,我們也在這裏使用新的關鍵字。 開關(strShoeType) { 案 「SPORTS」:返回新運動鞋展(); 突破; case「OFFICE」:return new OfficeShoe(); 突破; 默認值: 返回null; } 那爲什麼我們把它作爲一個工廠模式 – 2017-12-12 11:50:55