Xiao Peng

My personal blog moves to xiaopeng.me , blogs about design patterns will be synced to here.
肖鹏,ThoughtWorks资深咨询师,目前关注于架构模式、敏捷软件开发等领域,并致力于软件开发最佳实践的推广和应用。
多次为国内大型企业敏捷组织转型提供咨询和培训服务,在大型团队持续集成方面具有丰富的经验。
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

○。背景与背景知识

这是昨天在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模式。

二。引申问题

  1. 模式中factory method一定要是抽象的吗? NO.你可以定义一个默认的方法,生产某种Product。这样即使Factory没有子类也可以生产这种默认产品。通常这种情况下Factory是一个接口,然后定义一个BasicFactory来生产BasicProduct。其他的Factory由BasicFactory派生。注意,往往Factory和Product是平行的继承结构。
  2. Factory Method解耦了client和concreteProduct,是不是又引入了client和concreteFactory的耦合? 这个问题很好,答案是可能(《head first design patterns》一书中的例子就有这个问题),但是client端不应该依赖concreteFactory。如果依赖concreteFactory,那真是画蛇添足了(见wayfarer的文章)。
  3. Factory Method模式的好处有哪些?
    1. 封装了对象的创建。对象的创建如果使用new来完成,则与实现类(concreteProduct)是紧耦合的。Factory Method的创建行为factory method,返回Product接口,从而解耦了client和concreteProduct。
    2. 易于扩展。相对于Simple Factory模式,Factory Method模式可以通过派生进行扩展。

三。结论

一个纯的Factory Method模式其factory method不可以用static实现,通过与其他模式结合使用可以进行变通。而且通常情况下Factory Method模式都会与其他模式相结合。Abstract Factory模式通常就是用Factory Method模式来实现。