工厂方法与简单工厂非常相似,只要看看《设计模式》一书中对工厂方法的意图的描述就能很清楚地感受到这一点:定义一个用于创建对象的接口(PatternTesterFactory,再具体一点就是PatternTesterFactory类的CreatePattern方法),让子类决定实例化哪一个类(CreatePatternTester方法中的判断语意实现了这一过程)。对于这一意图,有两种方式可以实现,第一种是参数化的工厂方法,嗯…就是简单工厂了,这也是本文标题的来源;第二种方法通过以下步骤实现:
-
建立一个对象创建器类(可以用接口),该类有一个创建对象的方法。针对我的测试平台就是PatternTesterFactory类和CreatePatternTester方法,但是不在需要InitPatternTester方法。
-
为每一个PatternTester子类从PatternTesterFactory类派生一个具体的工厂类,实现其CreatePatternTester方法,令该方法返回这个子类的一个实例。
-
客户端需要PatternTester子类对象时,需要知道具体的工厂类,调用其CreatePatternTester方法以产生所需的对象。
这就有点奇怪了,好不容易通过简单工厂(参数化的工厂方法)去除了判断,怎么现在又把判断引进来了,既然是通过具体的工厂类产生对象,和new有什么区别?《设计模式》一书中说过这样做比直接用new更具有灵活性,还可以连接平行继承体系。具体的灵活性我没有感觉到,我倒觉得使用起来有点僵硬,并且从昨天发表的文章《代码的二十二道臭味》中可以看出出现平行继承体系结构时很可能就是写了具有坏味道代码。就拿《设计模式》中的那个例子来说,Figure的Manipulator要想操作figure对象,就必然要持有figure对象的信息,然而这些信息就存在figure对象中,如此看来manipulator类很可能就和figure类具有语意相同的字段,这又是二十二道臭味中的一味。我认为更合理的设计是将figure类的操作方法纳入自身,自己实现对自己操作的方法。
至于工厂方法的第二种实现形式的优点,从我的经验中是看不出来的,也许以后遇到了就知道了,MFC的文档类使用的就是这种方式,但是未必不可以用简单工厂方式实现。如果有人有这方面的经验,希望多多指点。
到此为止,已经写完了五个模式:简单工厂、模板方法、单例、原型、工厂方法。总结起来就是实现一个单例形式的简单工厂(工厂方法),简单工厂中的对象创建器可以使用原型模式,模板方法用来控制方法的执行流程。当把模板方法应用与对象生成器的时候(有的对象需要比较稳定的步骤来构建,但是可能每一步的构建方式不同)就得到了另一个新的模式——生成器(builder)。如果使用简单工厂的思维构建一个产生的不是具体产品而是另一个简单工厂的时候,也可以得到一个新的模式——抽象工厂(Abstract Factory)。后面将会写关于这两个模式的文章。
《设计模式》中各种模式的实现形式并不是死的,需要根据具体情况加以改变,同时尽力去领会各种模式中所蕴含的思想,希望有一天我惊奇地发现,对模式进行分类、命名只是为了方便交流!