○。背景与背景知识
这是昨天在QQ上举的一个例子。本文并不是从头讲Factory Method模式,仅对其实现细节进行讨论。关于这个模式可以参考wayfarer和吕震宇的文章。
一。分析
因为Factory Method(大写的Factory Method表示模式名称)模式的一个目的就是使得创建行为(factory method)(小写的factory method表示创建行为方法)抽象化,由子类实现,从而容易扩展。一个纯的Factory Method模式,其factory method是不能用static来实现的。通常Simple Factory模式才会由static来实现。
但是,一个Factory拥有一个static的创建方法是很诱人的。用户在任何时候只要用类名(Factory的类名)既可以创建出需要的Product。wayfarer 的文章最后给出的DotNet的实现部分就是这样的例子。吕震宇的另一篇文章 (关于Simple Factory模式)的回复中Walkdan给出的解决方案也是这样的。从本质上,这两个例子都不是纯的Factory Method模式或者Simple Factory模式,而是Simple Factory模式和Factory Method模式的组合应用。
引用Walkdan的回复:
Simple Factory最大的好处是把变化集中到了一处。另外,LightSimpleFactory.Create()里面的依赖关系也可以消除,我的做法是:
1. 声明构造子
public interface ILightCreator
{
Light Create();
}public class BulbLightCreator: ILightCreator
{
public Light Create()
{
return new BulbLight();
}
}
.2. 注册构造子
creators.Register("Bulb", new BulbLightCreator());
creators.Register("Tube", new TubeLightCreator());
.3. Simple Factory中创建对象
public class LightSimpleFactory.Create(string lightType)
{
ILightCreator creator = creators.Find(lightType);
return creator.Create();
}构造子其实就是Factory Method。这样, 通过注册构造子,3.中原来的switch()过程被消除,依赖关系随之解除。其中的Register(), Find()容易理解,方法就不写了。
新的类型可通过新注册构造子来实现扩展。当然2中的注册代码仅仅是示例,完全可以放到配置文件中去实现,比如:
<lightCreators>
<add name="Bulb" type="BulbLightCreator,"/>
<add name="Tube" type="TubeLightCreator,"/>
</lightCreators>
其ILightCreator继承体系,是Factory Method模式。LightSimpleFactory和creators的关系Walkdan没有说明,也可实现为Strategy模式。
二。引申问题
- 模式中factory method一定要是抽象的吗? NO.你可以定义一个默认的方法,生产某种Product。这样即使Factory没有子类也可以生产这种默认产品。通常这种情况下Factory是一个接口,然后定义一个BasicFactory来生产BasicProduct。其他的Factory由BasicFactory派生。注意,往往Factory和Product是平行的继承结构。
- Factory Method解耦了client和concreteProduct,是不是又引入了client和concreteFactory的耦合? 这个问题很好,答案是可能(《head first design patterns》一书中的例子就有这个问题),但是client端不应该依赖concreteFactory。如果依赖concreteFactory,那真是画蛇添足了(见wayfarer的文章)。
- Factory Method模式的好处有哪些?
- 封装了对象的创建。对象的创建如果使用new来完成,则与实现类(concreteProduct)是紧耦合的。Factory Method的创建行为factory method,返回Product接口,从而解耦了client和concreteProduct。
- 易于扩展。相对于Simple Factory模式,Factory Method模式可以通过派生进行扩展。
三。结论
一个纯的Factory Method模式其factory method不可以用static实现,通过与其他模式结合使用可以进行变通。而且通常情况下Factory Method模式都会与其他模式相结合。Abstract Factory模式通常就是用Factory Method模式来实现。