工厂的那些事儿

  下午考完试了,挺轻松的,不过现在不知道要干嘛了,随便写两句吧,也不知道要取个什么名字,就也时尚一下,叫成《工厂的那些事儿》吧 :)

  既然标题取成了工厂,那就是Factory Pattern了,前段时间看TerryLee大哥的工厂方法的文章,迷惑了几天,不过在某天早醒来的瞬间,我突然想通了,不过一直没有时间把它前下来,就趁这会儿有空,把它记录下来吧。

  First, 贴上TerryLee讲工厂方法那篇文章的地址:http://terrylee.cnblogs.com/archive/2006/01/04/310716.html

  下面引用的两段原文就是曾经引起我疑问的地方了:

Segment 1在应用程序中,我们要使用某一种日志记录方式,也许会用到如下这样的语句:
EventLog eventlog = new EventLog();
eventlog.Write();
当日志记录的方式从EventLog变化为FileLog,我们就得修改所有程序代码中出现上面语句的部分,这样的工作量是可想而知的。

Segment 2在应用程序中,Log对象的创建是频繁的,在这里我们可以把
LogFactory factory = new EventFactory();
这句话放在一个类模块中,任何需要用到Log对象的地方仍然不变。要是换一种日志记录方式,只要修改一处为:
LogFactory factory = new FileFactory();
其余的任何地方我们都不需要去修改。

  我曾一直想不通,如果把Segment 1中的 EventLog eventlog = new EventLog();改成Log log = new EventLog(),那会跟下面采用了Factory Method的情况会有多大的差别?大家都把变化范围缩小到了new的那一句,segment 1中只要 new EventLog()后,对后面的代码而言,都只是持有对抽象的Log的引用,segment 2中也一样,在后面都是持有对LogFactory这个抽象类的引用,大家的变化都在new的那一行,那引入工厂方法的意义在哪里?为什么TerryLee说Segment1中“这样的工作量是可想而知的”,而Segment中“只要修改一处”?

  带着这个疑问我用我笨重的大脑想了又想,终于在某一天早上醒来的瞬间想通了(好像我需要反醒我的智商了)。

  其实如果仅仅只是new了一个具体的日志类的话,引入工厂方法确实没有意义,如我的疑问中所说,两者的修改都只集中在对象的创建那一句,但是,如果我们在程序中需要用到十个不同的日志对象呢?在没有用工厂方法时,我们就要出现10次的Log log = new EventLog(),于是,依赖就开始在程序中遍布,一旦某天要改成文件日志,那就要在这10处修改,改成Log log = new FileLog()。

  而我们看看使用Factory Method的情形,首先创建一个工厂对象LogFactory logfactory = new EventLogFactory(),以后每次需要创建日志对象的时候,我们只需要:Log log = logFactory.Create(),为了得到10个不同的日志对象,我们只需要在创建工厂的那一行代码中依赖实现,其余地方都是依赖于抽象,一旦某日要换成文件日志,则只要在创建工厂的地方进行改动就可以了,相对于没有使用工厂方法的程序,耦合度的降低可想而知。

  如果在LogFactory logfactory = new EventLogFactory()这里利用反射来创建工厂,那就可以通过修改配置文件实现EventLog和FileLog以及将来要添加的日志记录器之间的更换,当然,你也可以想到在Segment1中使用反射,但如果这样的话,我们创建10个日志对象,就得在10个地方写上反射代码,而这些代码都是冗余的。

  总结一下,工厂方法引入后到底解决了什么问题?工厂工厂,从空面意思就可以想到,它一定跟创建大量的产品有关,就像上面的Segment1和Segment2,如果程序只需要一个日志对象(Log)就完事儿,那引入工厂方法反而多写了代码,没有意义,但是当要创建多个产品(Log)时,工厂的优势就出来了,他可以让耦合隔离到一行代码中,而Segment1中则不行。

  这是工厂方法,还有一种Design Pattern叫做Abstract Factory,大家都跟工厂有关,那也就是说,他们对大批量创建产品(对象)的情况是很有用的,但他跟工厂方法又不同,如上所述,工厂方法生产来生产去也就生产出了一种产品――日志对象,而抽象工厂相对于它,不同的地方就在于抽象工厂可以生厂“一系列”的产品,和和,看来抽象工厂的规模比较大,厂长也比较有钱咯。

  就像工厂方法一样,如果只是创建一个实例,工厂就没有什么太大意义(要是只创建一个,我自己手工做就好了,何必要去盖一个工厂来呢?钱太多了么?),抽象工厂的外观就像下面这样:

public abstract Factory {
    
public AbstractProductA CreateProductA();
    
public AbstractProductB CreateProductB();
    
public AbstractProductC CreateProductC();
    
//… …
}

  当然,各种的Product不能完全没有关系,要不然把牛头和马嘴放到一个工厂类中去生产,那好像就有点对不起“高内聚”大哥了哈。

  之后,要创建产品时,只要new一个继承了Factory的具体工厂,再不停的CreateProduct*(),就可以得到许多的产品了。

  总结一句,工厂方法和抽象工厂,前者只生产一种产品,而后者是生产一个产品系列。当然,如果本身产品种类就是多变的,今天要让工厂会生产ProductE,后天又要让工厂会生厂ProductM,那抽象工厂也无能为力了。

  THE END.

  
posted @ 2008-07-06 20:36  水言木  阅读(3590)  评论(0编辑  收藏  举报