工厂方法模式

工厂方法模式,是用来创建一个对象的。

它的意图是定义一个用于创建对象的接口,让子类决定实例化哪一个类。将实例化延迟到其子类。

当一个类需要实例化另一个类的派生类,但不知道具体是哪个派生类。工厂方法模式允许让派生类来做决定。

举例来说,一个生产汽车的厂家,需要生产一辆汽车并进行相关工作,例如测试之类的,那么由高层来指定生产哪种型号的汽车,如果只使用一个汽车工厂的话,若今天生产A型汽车,所用的是A型汽车的生产工具和配置,到了明日要生产B型汽车,那么只能把这个汽车工厂变成适合生产B型汽车,改变原有的生产工具和配置。

这就是变化。

这种变化需要消耗大量的人力无力,特别是变化无比频繁的时候:今天生产A型汽车、明天生产B型汽车、后天生产C型、大后天又需要生产A型……

每天都需要不断地改变这个汽车工厂,但这并不是最糟糕的。将它看成程序语言的话,我们就可以看出变化带来的可怕之处。

public class App

{

  public static void main()

  {

    //主程序是做决策的高层,今天他要生产A型汽车

    carFactory factory = new carFactory();

    CarA carA = factory.create();

  }

}

//这是汽车工厂

public class carFactory

{

  public CarA create(){return new CarA;}

  public void someMethodForCreateCarA_tool1(){}

  public void someMethodForCreateCarA()_tool2(){}

  ……

}

现在到了第二天,高层决定要生产B型汽车,那么哪些会改变了呢?

首先是主程序,这代表高层的决策,是非变不可的。

main函数中变成这样:

carFactory factory = new carFactory();

CarB carB = factory.create();

然后要变的是汽车工厂

public class carFactory

{

  public CarB create(){return new CarB;}

  public void someMethodForCreateCarB_tool1(){}

  public void someMethodForCreateCarB_tool2(){}

  ……

}

看,整个汽车工厂都要改变了,变成适合生产B型汽车。

下面我将展示变化带来的更可怕的灾难。

一辆车生产出来,它还要做一些其他事才行吧,比如测试。

那么,

class testCar

{

  public test(CarA carA){}

  public sometestforcarA(){}

  ……

}

这样的话,连整个测试框架都要更改了,从程序角度看,如果carA和carB的接口一致的话,或许我们只需要将CarA的名字替换成CarB便行了,但这也是改变,改变会带来重新编译,重新部署,还有无法预料的问题。

继测试之后,如果还有一系列工作,那么这一系列的工作将全部改变!因为这些工作都与汽车这个对象有着强依赖关系!

这就是需要工厂方法模式的地方。

想象一下,我们为没一种型号的汽车配备一个汽车工厂(这在现实中似乎不太可能),若要生产A型汽车便送到汽车工厂A去生产,生产B型汽车则送到B型汽车工厂,如果没B型汽车工厂则造一个……

从现实的角度看似乎不太合理,那让我们从程序的角度出发。

Code

构造了一个汽车工厂的抽象类,当我们需要生产A型汽车时,便建造汽车工厂A

Code

 

需要生产B型汽车呢?

Code

 

这样的话,我们便不需要改变工厂了,我们做的已成为了扩展。

故设计模式就是这样:拒绝改变,允许扩展!

 

接下来再看,构造不同的汽车工厂,虽然减少了改变,但测试汽车这些工作进行的时候会怎么样呢?强依赖关系依然存在!

所以我们要给减少这种强依赖。(依赖是不能杜绝的,只能将它减少到一个可控制的范围内!)

 

Code

 

给汽车也构建一个抽象类,需要A型汽车时:

Code

 

需要B型汽车时:

Code

 

然后我们还要给它做一系列测试等工作

Code

 

这样的话,我们已经将所有的改变集中到主函数中了

Code

 

下一次,当变化来临时,比如高层发话要生产X型汽车,我们只需改变两点,一是构建新的汽车工厂、新的汽车类(这两个类可以在一个文件中),二是主函数,将工厂实例改为CarXFactory。

除此之外其他都无需改变。

甚至,我们可以将构建工厂实例的过程动态实现,根据配置文件,让程序自动创建对象实例。新的汽车工厂和汽车类编译成DLL递交给客户即可,完全不再需要动源程序了!

-----------------------------------------------

以上是我看了李建忠老师的视频后的一点感悟和愚见。

 

posted on 2009-02-28 14:23  lolicon  阅读(188)  评论(0编辑  收藏  举报