工厂方法

工廠方法模式（英語：Factory method pattern）是一種實現了「工廠」概念的物件導向設計模式。就像其他建立型模式一樣，它也是處理在不指定物件具體類型的情況下建立物件的問題。工廠方法模式的實質是「定義一個建立物件的介面，但讓實現這個介面的類來決定實體化哪個類。工廠方法讓類別的實體化推遲到子類別中進行。」
建立一個物件常常需要複雜的過程，所以不適合包含在一個複合物件中。建立物件可能會導致大量的重複程式碼，可能會需要複合物件存取不到的資訊，也可能提供不了足夠級別的抽象，還可能並不是複合物件概念的一部分。工廠方法模式通過定義一個單獨的建立物件的方法來解決這些問題。由子類別實現這個方法來建立具體類型的物件。
物件建立中的有些過程包括決定建立哪個物件、管理物件的生命周期，以及管理特定物件的建立和銷毀的概念。

工廠

在物件導向程式設計中，工廠通常是一個用來建立其他物件的物件。工廠是構造方法的抽象，用來實現不同的分配方案。
工廠物件通常包含一個或多個方法，用來建立這個工廠所能建立的各種類型的物件。這些方法可能接收參數，用來指定物件建立的方式，最後返回建立的物件。
有時，特定類型物件的控制過程比簡單地建立一個物件更複雜。在這種情況下，工廠物件就派上用場了。工廠物件可能會動態地建立產品類的物件，或者從物件池中返回一個物件，或者對所建立的物件進行複雜的組態，或者應用其他的操作。
這些類型的物件很有用。幾個不同的設計模式都應用了工廠的概念，並可以使用在很多語言中。例如，在《設計模式》一書中，像工廠方法模式、抽象工廠模式、生成器模式，甚至是單例模式都應用了工廠的概念。

程式碼舉例

例如，有一個Button類表示按鈕，另有它的兩個子類別WinButton和MacButton分別代表Windows和Mac風格的按鈕，那麼這幾個類和用於建立它們的工廠類在Java中可以如下實現（在此省略所有類和方法的可見性設定）：
//幾個Button類class Button{/* ...*/}class WinButton extends Button{/* ...*/}class MacButton extends Button{/* ...*/}//他們的工廠類interface ButtonFactory{
    abstract Button createButton();}class WinButtonFactory implements ButtonFactory{
    Button createButton(){
        return new WinButton();
    }}class MacButtonFactory implements ButtonFactory{
    Button createButton(){
        return new MacButton();
    }}

變種

雖然工廠方法模式的背後動機是允許子類別選擇建立物件的具體類型，但是使用工廠方法模式也有一些其他的好處，其中很多並不依賴於子類別。因此，有時候也會建立不使用多型性建立物件的工廠方法，以得到使用工廠方法的其他好處。

工廠「方法」而非工廠「類」

如果拋開設計模式的範疇，「工廠方法」這個詞也可以指作為「工廠」的方法，這個方法的主要目的就是建立物件，而這個方法不一定在單獨的工廠類中。這些方法通常作為靜態方法，定義在方法所實體化的類中。
每個工廠方法都有特定的名稱。在許多物件導向的程式語言中，構造方法必須和它所在的類具有相同的名稱，這樣的話，如果有多種建立物件的方式（多載）就可能導致歧義。工廠方法沒有這種限制，所以可以具有描述性的名稱。舉例來說，根據兩個實數建立一個複數，而這兩個實數表示直角坐標或極坐標，如果使用工廠方法，方法的含義就非常清晰了。當工廠方法起到這種消除歧義的作用時，構造方法常常被設定為私有方法，從而強制用戶端程式碼使用工廠方法建立物件。
下面的例子展示了在不同的程式語言中實現複數建立的程式碼：

Java

class Complex {
     public static Complex fromCartesianFactory(double real, double imaginary) {
         return new Complex(real, imaginary);
     }
     public static Complex fromPolarFactory(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }
     private Complex(double a, double b) {
         //...
     }}Complex product = Complex.fromPolarFactory(1, pi);

VB.NET

Public Class Complex
    Public Shared Function fromCartesianFactory(real As Double, imaginary As Double) As Complex
        Return (New Complex(real, imaginary))
    End Function

    Public Shared Function fromPolarFactory(modulus As Double, angle As Double) As Complex
        Return (New Complex(modulus * Math.Cos(angle), modulus * Math.Sin(angle)))
    End Function

    Private Sub New(a As Double, b As Double)
        '...
    End SubEnd ClassComplex product = Complex.fromPolarFactory(1, pi);

C#

public class Complex{
    public double real;
    public double imaginary;
    public static Complex fromCartesianFactory(double real, double imaginary ) 
    {
        return new Complex(real, imaginary);
    }

    public static Complex  fromPolarFactory(double modulus , double angle ) 
    {
        return new Complex(modulus * Math.Cos(angle), modulus * Math.Sin(angle));
    }
       
 
    private Complex (double a, double b)
    {
        real = a;
        imaginary = b;
    }}Complex product = Complex.fromPolarFactory(1,pi);

簡單工廠

普通的工廠方法模式通常伴隨著物件的具體類型與工廠具體類型的一一對應，用戶端程式碼根據需要選擇合適的具體類型工廠使用。然而，這種選擇可能包含複雜的邏輯。這時，可以建立一個單一的工廠類，用以包含這種選擇邏輯，根據參數的不同選擇實現不同的具體物件。這個工廠類不需要由每個具體產品實現一個自己的具體的工廠類，所以可以將工廠方法設定為靜態方法。
而且，工廠方法封裝了物件的建立過程。如果建立過程非常複雜（比如依賴於設定檔或用戶輸入），工廠方法就非常有用了。
比如，一個程式要讀取圖檔。程式支援多種圖像格式，每種格式都有一個對應的ImageReader類用來讀取圖像。程式每次讀取圖像時，需要基於檔案資訊建立合適類型的ImageReader。這個選擇邏輯可以包裝在一個簡單工廠中：
public class ImageReaderFactory {
    public static ImageReader imageReaderFactoryMethod(InputStream is) {
        ImageReader product = null;

        int imageType = determineImageType(is);
        switch (imageType) {
            case ImageReaderFactory.GIF:
                product = new GifReader(is);
            case ImageReaderFactory.JPEG:
                product = new JpegReader(is);
            //...
        }
        return product;
    }}