
_START_ARTICLE_
工厂方法
_START_PARAGRAPH_
工厂方法模式（英语：Factory method pattern）是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样，它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口，但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”_NEWLINE_创建一个对象常常需要复杂的过程，所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码，可能会需要复合对象访问不到的信息，也可能提供不了足够级别的抽象，还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。_NEWLINE_对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期，以及管理特定对象的创建和销毁的概念。
_START_SECTION_
工厂
_START_PARAGRAPH_
在面向对象程序设计中，工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象，用来实现不同的分配方案。_NEWLINE_工厂对象通常包含一个或多个方法，用来创建这个工厂所能创建的各种类型的对象。这些方法可能接收参数，用来指定对象创建的方式，最后返回创建的对象。_NEWLINE_有时，特定类型对象的控制过程比简单地创建一个对象更复杂。在这种情况下，工厂对象就派上用场了。工厂对象可能会动态地创建产品类的对象，或者从对象池中返回一个对象，或者对所创建的对象进行复杂的配置，或者应用其他的操作。_NEWLINE_这些类型的对象很有用。几个不同的设计模式都应用了工厂的概念，并可以使用在很多语言中。例如，在《设计模式》一书中，像工厂方法模式、抽象工厂模式、生成器模式，甚至是单例模式都应用了工厂的概念。
_START_SECTION_
代码举例
_START_PARAGRAPH_
例如，有一个Button类表示按钮，另有它的两个子类WinButton和MacButton分别代表Windows和Mac风格的按钮，那么这几个类和用于创建它们的工厂类在Java中可以如下实现（在此省略所有类和方法的可见性设置）：_NEWLINE_//幾個Button類class Button{/* ...*/}class WinButton extends Button{/* ...*/}class MacButton extends Button{/* ...*/}//他們的工廠類interface ButtonFactory{_NEWLINE_    abstract Button createButton();}class WinButtonFactory implements ButtonFactory{_NEWLINE_    Button createButton(){_NEWLINE_        return new WinButton();_NEWLINE_    }}class MacButtonFactory implements ButtonFactory{_NEWLINE_    Button createButton(){_NEWLINE_        return new MacButton();_NEWLINE_    }}
_START_SECTION_
变种
_START_PARAGRAPH_
虽然工厂方法模式的背后动机是允许子类选择创建对象的具体类型，但是使用工厂方法模式也有一些其他的好处，其中很多并不依赖于子类。因此，有时候也会创建不使用多态性创建对象的工厂方法，以得到使用工厂方法的其他好处。
_START_SECTION_
工厂“方法”而非工厂“类”
_START_PARAGRAPH_
如果抛开设计模式的范畴，“工厂方法”这个词也可以指作为“工厂”的方法，这个方法的主要目的就是创建对象，而这个方法不一定在单独的工厂类中。这些方法通常作为静态方法，定义在方法所实例化的类中。_NEWLINE_每个工厂方法都有特定的名称。在许多面向对象的编程语言中，构造方法必须和它所在的类具有相同的名称，这样的话，如果有多种创建对象的方式（重载）就可能导致歧义。工厂方法没有这种限制，所以可以具有描述性的名称。举例来说，根据两个实数创建一个复数，而这两个实数表示直角坐标或极坐标，如果使用工厂方法，方法的含义就非常清晰了。当工厂方法起到这种消除歧义的作用时，构造方法常常被设置为私有方法，从而强制客户端代码使用工厂方法创建对象。_NEWLINE_下面的例子展示了在不同的编程语言中实现复数创建的代码：
_START_SECTION_
Java
_START_PARAGRAPH_
class Complex {_NEWLINE_     public static Complex fromCartesianFactory(double real, double imaginary) {_NEWLINE_         return new Complex(real, imaginary);_NEWLINE_     }_NEWLINE_     public static Complex fromPolarFactory(double modulus, double angle) {_NEWLINE_         return new Complex(modulus * cos(angle), modulus * sin(angle));_NEWLINE_     }_NEWLINE_     private Complex(double a, double b) {_NEWLINE_         //..._NEWLINE_     }}Complex product = Complex.fromPolarFactory(1, pi);
_START_SECTION_
VB.NET
_START_PARAGRAPH_
Public Class Complex_NEWLINE_    Public Shared Function fromCartesianFactory(real As Double, imaginary As Double) As Complex_NEWLINE_        Return (New Complex(real, imaginary))_NEWLINE_    End Function_NEWLINE__NEWLINE_    Public Shared Function fromPolarFactory(modulus As Double, angle As Double) As Complex_NEWLINE_        Return (New Complex(modulus * Math.Cos(angle), modulus * Math.Sin(angle)))_NEWLINE_    End Function_NEWLINE__NEWLINE_    Private Sub New(a As Double, b As Double)_NEWLINE_        '..._NEWLINE_    End SubEnd ClassComplex product = Complex.fromPolarFactory(1, pi);
_START_SECTION_
C#
_START_PARAGRAPH_
public class Complex{_NEWLINE_    public double real;_NEWLINE_    public double imaginary;_NEWLINE_    public static Complex fromCartesianFactory(double real, double imaginary ) _NEWLINE_    {_NEWLINE_        return new Complex(real, imaginary);_NEWLINE_    }_NEWLINE__NEWLINE_    public static Complex  fromPolarFactory(double modulus , double angle ) _NEWLINE_    {_NEWLINE_        return new Complex(modulus * Math.Cos(angle), modulus * Math.Sin(angle));_NEWLINE_    }_NEWLINE_       _NEWLINE_ _NEWLINE_    private Complex (double a, double b)_NEWLINE_    {_NEWLINE_        real = a;_NEWLINE_        imaginary = b;_NEWLINE_    }}Complex product = Complex.fromPolarFactory(1,pi);
_START_SECTION_
简单工厂
_START_PARAGRAPH_
普通的工厂方法模式通常伴随着对象的具体类型与工厂具体类型的一一对应，客户端代码根据需要选择合适的具体类型工厂使用。然而，这种选择可能包含复杂的逻辑。这时，可以创建一个单一的工厂类，用以包含这种选择逻辑，根据参数的不同选择实现不同的具体对象。这个工厂类不需要由每个具体产品实现一个自己的具体的工厂类，所以可以将工厂方法设置为静态方法。_NEWLINE_而且，工厂方法封装了对象的创建过程。如果创建过程非常复杂（比如依赖于配置文件或用户输入），工厂方法就非常有用了。_NEWLINE_比如，一个程序要读取图像文件。程序支持多种图像格式，每种格式都有一个对应的ImageReader类用来读取图像。程序每次读取图像时，需要基于文件信息创建合适类型的ImageReader。这个选择逻辑可以包装在一个简单工厂中：_NEWLINE_public class ImageReaderFactory {_NEWLINE_    public static ImageReader imageReaderFactoryMethod(InputStream is) {_NEWLINE_        ImageReader product = null;_NEWLINE__NEWLINE_        int imageType = determineImageType(is);_NEWLINE_        switch (imageType) {_NEWLINE_            case ImageReaderFactory.GIF:_NEWLINE_                product = new GifReader(is);_NEWLINE_            case ImageReaderFactory.JPEG:_NEWLINE_                product = new JpegReader(is);_NEWLINE_            //..._NEWLINE_        }_NEWLINE_        return product;_NEWLINE_    }}