1 意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method 使一个类的实例化延迟到其子类。
2 别名
虚构造器(Virtual Constructor)
3 动机
框架使用抽象类定义和维护对象之间的关系。这些对象的创建通常也由框架负责。
4 适用性
- 当一个类不知道它所必须创建的对象的类的时候。
- 当一个类希望由它的子类来指定它所创建的对象的时候。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
5 结构
6 参与者
- Product(Document):
- 定义工厂方法所创建的对象的接口。
- ConcreteProduct(MyDocument)
- 实现 Product 接口。
- Creator(Application)
- 声明工厂方法,该方法返回一个 Product 类型的对象。Creator 也可以定义一个工厂方法的缺省实现,它返回一个缺省的 ConcreteProduct 对象。
- 可以调用工厂方法以创建一个 Product 对象。
- ConcreteCreator(MyApplication)
- 重定义工厂方法以返回一个 ConcreteProduct 实例。
7 协作
Creator依赖于它的子类来定义工厂方法,所以它返回一个适当的ConcreteProduct实例。
8 效果
工厂方法不再将与特定应用有关的类绑定到你的代码中。代码仅处理 Product 接口;因此它可以与用户定义的任何 ConcreteProduct 类一起使用。
工厂方法的一个潜在缺点在于客户可能仅仅为了创建一个特定的 ConcreteProduct 对象,就不得不创建 Creator 的子类。当 Creator 子类不必需时,客户现在必然要处理类演化的其他方面;但是当客户无论如何必须创建 Creator 的子类时,创建子类也是可行的。
- 为子类提供挂钩(hook):用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。Factory Method 给子类一个挂钩以提供对象的扩展版本。
- 连接平行的类层次:当一个类将它的一些职责委托给一个独立的类的时候,就产生了平行类层次。
9 实现
- 主要有两种不同的情况
- 1 第一种情况:Creator类是一个抽象类并且不提供它所声明的工厂方法的实现。需要子类来定义实现,因为没有合理的缺省实现。它避免了不得不实例化不
可预见类的问题。 - 2 第二种情况:Creator是一个具体的类而且为工厂方法提供一个缺省的实现。也有可能有一个定义了缺省实现的抽象类,但这不太常见。具体的Creator主要因为灵活性才使用工厂方法。它所遵循的准则是,“用一个独立的操作创建对象,这样子类才能重定义它们的创建方式。”这条准则保证了子类的设计者能够在必要的时候改变父类所实例化的对象的类。
- 1 第一种情况:Creator类是一个抽象类并且不提供它所声明的工厂方法的实现。需要子类来定义实现,因为没有合理的缺省实现。它避免了不得不实例化不
- 参数化工厂方法
- 该模式的另一种情况使得工厂方法可以创建多种产品。工厂方法采用一个标识要被创建的对象种类的参数。工厂方法创建的所有对象将共享Product接口。在Document的例子中,Application可能支持不同种类的Document。你给CreateDocument传递一个外部参数来指定将要创建的文档的种类。
- 特定语言的变化和问题
- 使用模板以避免创建子类
- 命名约定
10 代码示例
Product
1
2
3class IProduct
{
}ConcreteProduct
1
2
3
4
5
6
7class ConcreteProduct : IProduct
{
public ConcreteProduct()
{
Console.WriteLine("具体产品");
}
}Creator
1
2
3
4
5
6
7
8
9
10
11
12
13abstract class Creator
{
public abstract IProduct FactoryMethod();
/// <summary>
/// 工厂方法的缺省实现
/// </summary>
/// <returns></returns>
public IProduct Create()
{
return this.FactoryMethod();
}
}ConcreteCreator
1
2
3
4
5
6
7
8class ConcreteCreator : Creator
{
public override IProduct FactoryMethod()
{
IProduct product = new ConcreteProduct();
return product;
}
}Main
1
2
3
4
5
6
7
8
9
10class Program
{
static void Main(string[] args)
{
Creator creator = new ConcreteCreator();
creator.Create();
Console.ReadLine();
}
}
11 已知应用
工厂方法主要用于工具包和框架中。
12 相关模式
- AbstractFactory:经常用工厂方法来实现。AbstractFactory 模式中动机一节的例子也对FactoryMethod进行了说明。工厂方法通常在TemplateMethods(5.10)中被调用。在上面的文档例子中,NewDocument就是一个模板方法。
- Prototypes:不需要创建Creator的子类。但是,它们通常要求一个针对Product类的Initialize操作。Creator使用Initialize来初始化对象。而FactoryMethod不需要这样的操作。