工厂方法模式

工厂方法模式（）是一种实现了工厂概念的面向对象设计模式。就像其他创建型模式一样，它也是处理在不指定对象具体类型的情况下创建对象的问题。
概述.
对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期，以及管理特定对象的建立和销毁的概念。工厂方法模式的实质是“定义一个创建对象的接口，但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
创建一个对象常常需要复杂的过程，所以不适合包含在一个复合对象中。创建对象可能会导致大量的重复代码，可能会需要复合对象访问不到的信息，也可能提供不了足够级别的抽象，还可能并不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。
结构.
在上面的UML类图中，codice_1类要求codice_2对象，但不直接的实例化codice_3类。codice_1转而提及一个独立的codice_5来创建一个产品对象，这使得codice_1独立于被实例化的确切的具体类。codice_1的子类可以精制（redefine）出哪个类要被实例化。在这个例子中，codice_8子类通过实例化codice_3类来实现抽象的codice_5。
代码举例.
Java.
下面的迷路园游戏的Java例子，类似于《设计模式》中的例子，这里针对而简化了对房间的四面、门和墙的处置，即一个房间与毗邻的另一个房间，如果二者连通则其间有开着的一个门，如果二者不连通则其间有一个墙；永远开着的门通常就表现为房间的这一面没有墙，如果要将门具象表现出来则附含着其所处在的墙。
抽象类codice_11连通多个codice_12对象，但是将创建codice_12对象的责任委托给了作为具体类的它的子类。codice_14构造器是增加一些公用逻辑的模板方法，其中涉及了作为虚方法的codice_15工厂方法，它在codice_11的子类中被覆写，从而可以使用上各种不同的房间：
public abstract class Room {
 abstract void connect(Room room);
public class MagicRoom extends Room {
public class OrdinaryRoom extends Room {
public abstract class MazeGame {
 private final List&lt;Room&gt; rooms = new ArrayList&lt;&gt;();
 abstract protected Room makeRoom();
 public MazeGame() {
 Room room1 = makeRoom();
 Room room2 = makeRoom();
 room1.connect(room2);
 rooms.add(room1);
 rooms.add(room2);
public class MagicMazeGame extends MazeGame {
 @Override
 protected MagicRoom makeRoom() {
 return new MagicRoom();
public class OrdinaryMazeGame extends MazeGame {
 @Override
 protected OrdinaryRoom makeRoom() {
 return new OrdinaryRoom();
MazeGame ordinaryGame = new OrdinaryMazeGame();
MazeGame magicGame = new MagicMazeGame();
Python.
Python的迷路园游戏例子：
from abc import ABC, abstractmethod
class Room(ABC):
 descr = None
 def __init__(self, **kwargs):
 self.connected_rooms = []
 params = type(self).params | kwargs
 for key, value in params.items():
 self.__dict__[key] = value
 def __str__(self): 
 return type(self).descr
 @abstractmethod
 def connect(self, other, **kwargs): 
 self.connected_rooms.append(other)
class OrdinaryRoom(Room):
 descr = 'Ordinary room'
 def connect(self, other):
 super().connect(other, kw0=")
class MagicRoom(Room):
 descr = 'Magic room'
 def connect(self, other):
 super().connect(other, kw0=")
class MazeCreatorTrait(ABC):
 def __init__(self):
 self.rooms = []
 room1 = self.room_factory(kw2=")
 room2 = self.room_factory(kw2=")
 room1.connect(room2)
 self.rooms.append(room1)
 self.rooms.append(room2)
 @abstractmethod
 def room_factory(self): pass
 def play(self):
 print(f"Playing using {self.rooms[0]}")
class MazeCreator(MazeCreatorTrait):
 def __init__(self, creator_cls=OrdinaryRoom):
 self.creator_cls = creator_cls
 super().__init__()
 def room_factory(self, **kwargs):
 return self.creator_cls(**kwargs)
其执行：
»&gt; maze1 = MazeCreator()
»&gt; maze1.play()
Playing using Ordinary room
»&gt; maze2 = MazeCreator(MagicRoom)
»&gt; maze2.play()
Playing using Magic room
C++.
《设计模式》书中早于C++98的例子的C++23实现：
import std;
enum class ProductId {MINE, YOURS};
// defines the interface of objects the factory method creates.
class Product {
public:
 virtual void print() = 0;
 virtual ~Product() = default;
// implements the Product interface.
class ConcreteProductMINE: public Product {
public:
 void print() {
 std::println("this={} print MINE", this);
};
// implements the Product interface.
class ConcreteProductYOURS: public Product {
public:
 void print() {
 std::println("this={} print YOURS", this);
};
// declares the factory method, which returns an object of type Product.
class Creator {
public:
 virtual std::unique_ptr&lt;Product&gt; create(ProductId id) {
 if (ProductId::MINE == id) return std::make_unique&lt;ConcreteProductMINE&gt;();
 if (ProductId::YOURS == id) return std::make_unique&lt;ConcreteProductYOURS&gt;();
 // repeat for remaining products...
 return nullptr;
 virtual ~Creator() = default;
int main() {
 // The unique_ptr prevent memory leaks.
 std::unique_ptr&lt;Creator&gt; creator = std::make_unique&lt;Creator&gt;();
 std::unique_ptr&lt;Product&gt; product = creator-&gt;create(ProductId::MINE);
 product-&gt;print();
 product = creator-&gt;create(ProductId::YOURS);
 product-&gt;print();
程序输出：
this=0x6e5e90 print MINE
this=0x6e62c0 print YOURS
C#.
下面是C#例子：
public interface IProduct {
 string GetName();
 bool SetPrice(double price);
public class Phone : IProduct {
 private double _price;
 public string GetName() {
 return "Apple TouchPad";
 public bool SetPrice(double price) {
 _price = price;
 return true;
/* Almost same as Factory, just an additional exposure to do something with the created method */
public abstract class ProductAbstractFactory {
 protected abstract IProduct MakeProduct();
 public IProduct GetObject() // Implementation of Factory Method. {
 return this.MakeProduct();
public class PhoneConcreteFactory : ProductAbstractFactory {
 protected override IProduct MakeProduct() {
 IProduct product = new Phone();
 // Do something with the object after receiving it
 product.SetPrice(20.30);
 return product;
适用性.
工厂方法模式，适用于基于接口编程与实现依赖反转原则。
下列情况可以考虑使用工厂方法模式：
工厂方法模式常见于工具包和框架中，在这些库中可能需要创建客户端代码实现的具体类型的对象。
平行的类层次结构中，常常需要一个层次结构中的对象能够根据需要创建另一个层次结构中的对象。
工厂方法模式可以用于测试驱动开发，从而允许将类放在测试中。举例来说，codice_24这个类创建了一个codice_25对象，但是codice_25对象不能放在自动的单元测试中（可能它需要访问产品数据库，而这个数据库不是随时能够访问到的）。所以，就可以把codice_25对象的创建交由codice_24类的一个方法（虚函数）codice_29完成。为了测试，再创建一个codice_24的一个子类codice_31，重写codice_29方法，在方法中创建并返回一个codice_33（codice_25的子类），而这是一个模拟对象。这样，单元测试就可以使用codice_31来测试codice_24的功能，从而避免了使用codice_25对象带来的副作用。