Brave Ostrich


肖鹏是ThoughtWorks中国公司的咨询师,目前关注于架构模式、敏捷软件开发等领域,并致力于软件开发最佳实践的推广和应用。
  博客园 :: 首页 ::  :: 联系 :: 订阅 订阅 :: 管理

一.引子

GOF的23个模式中与Factory相关的有两个,一个是Factory Method,另一个是Abstract Factory模式。还有一个是Simple Factory,是深入浅出设计模式这本书定义的。这里面没有Factory这个模式,很多人都没有注意到这一点(包括idior,谁让你有名呢:)。

*如果您对创建型模式特别是Factory MethodAbstract FactorySimple Factory还没有初步了解,建议你先看看博客园设计模式团队相关的文章。

二.讨论

提出这一点来绝对不是哗众取宠,关键是这个“Method”很重要。我们先来看看GOF的书中关于Factory Method的类图结构:

Idior说很多人没有注意到AnOperation这个方法,也许是这样的,但是这个方法并不重要。工厂方法的意图一节中指出:工厂方法定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。其别名是虚拟构造器。从其意图和别名中都看不出AnOperation这个方法。当然为了说明这个方法不重要,我还必须给出一个例子:该例子使用了Factory Method模式,而又不存在AnOperation方法。有吗?有,就是Abstract Factory模式。

《DP》中在说到Abstract Factory模式的实现的时候,指出AbstractFactory仅声明一个创建产品的接口,真正创建产品是由ConcreteProduct子类实现的。最通常的办法是为每一个产品定义一个工厂方法(参见Factory Method(3.3))。一个具体的工厂将为每个产品重定义该工厂方法以指定产品。从这里我们可以看出来:Factory Method和Abstract Factory不是一个层次上的模式。前者是实现后者的一些有用技术之一。(《DP》中的说法是:Here are some useful techniques for implementing the Abstract Factory pattern.)GOF也多次强调,自己给出的类图只是一个例子,一种实现(我找到原话再贴过来:)。所以我们不应该拘泥于《DP》中的类图。

在新手中,一个常见的误解是Factory Method应该有一个独立的Factory类。这是新手才会犯的错误,Factory Method,只是一个Method而已。任何时候,当你存在一个虚拟的(抽象的)函数其返回值是一个接口(抽象类),你就在使用Factory Method了。我们不关心谁调用这个方法,这个方法的参数如何。理解一个模式的简单性往往比理解其复杂性更重要。

那么Factory Method是不是可以有一个独立的Factory类与其对应呢?当然可以,而且恭喜你,如果你的独立的Factory类中包含几个Factory Method,你已经在使用Abstract Factory了。注意不要跟Simple Factory模式弄混,Simple Factory虽然也包含创建对象的方法,但是并没有使用Factory Method模式。

我们再来看看Abstract Factory的类图: 

 

在这个类图中CreateProductA()和CreateProductB()都是Factory Method(而没有出现AnOperation()这样的方法)。

三.结论:

虽然这篇随笔已经很短了,我仍然愿意总结一下前面所说的话,以节省您的时间:)

1. 没有Factory这个模式,大多数人提到Factory模式的时候,实际上指的是Factory Method。

2. Factory Method模式不要求一个独立的工厂类,该模式的核心是一个虚拟的(抽象的)方法,该方法返回一个产品的接口。

3. Factory Method和Abstract Factory不是一个层次上的模式,前者是后者赖以实现的一项技术,后者可以从前者演化而来。关于演化过程请参考idior的这篇文章

四.并非闲话

不记得是idior,TerryLee或者吕兄中的哪一位提出的“纯”的设计模式这个说法,指的是最简单的而符合某个模式的定义的实现。我们见到的设计模式的实现往往是或与其他模式混合使用,或者对具体应用做了妥协,使得我们看不到“纯”的设计模式,也就看不到模式的简单性。而理解模式的简单性对于我们认识模式的实质是非常重要的,就像是在化学里面分析原子的特性一样。

五.何谓Factory(From《重构与模式》)

Factory一词是业内滥用最厉害和最不精确的术语之一。有些人使用“Factory模式”一词指代Factory Method[DP]模式,有些人使用这个术语表示Abstract Factory[DP]模式,有些人使用这个术语表示这两个模式,而有些人则使用这个词表示任何创建对象的代码。

......

下图中使用粗线表示创建对象的方法,说明了Factory Method,Factory(书中所指的Factory,笔者注)和Abstract Factory结构之间的区别。

Feedback

#1楼   回复  引用  查看    

2006-12-03 16:43 by TerryLee      
看不到“纯”的设计模式,也就看不到模式的简单性。而理解模式的简单性对于我们认识模式的实质是非常重要的,就像是在化学里面分析原子的特性一样。
================================
深表同意,只有理解了“纯”的设计模式,才有可能在实际开发中综合运用设计模式,去权衡和取舍。

刚才看了一篇文章,有点生气,连简单工厂模式和抽象工厂模式都没区分
http://www.cnblogs.com/xuanfeng/archive/2006/12/03/580348.html">http://www.cnblogs.com/xuanfeng/archive/2006/12/03/580348.html

#2楼   回复  引用  查看    

2006-12-03 16:43 by Justin      
关于工厂,园子里和各种书上,看过太多了,但是目前我见到的讲的最好的却是李建忠老师的MSDN在线讲座。
http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/consyscourse/CsharpOOD.aspx">http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/consyscourse/CsharpOOD.aspx

#3楼   回复  引用  查看    

2006-12-03 16:59 by Dflying Chen      
看不太懂……学习一下

#4楼[楼主]   回复  引用  查看    

2006-12-03 17:14 by 肖鹏      
@TerryLee
别生气,你的回复太太...激烈了。建议你去掉极其混乱这句话,毕竟人家没有放到首页上去。今天连着放了两篇首页,好怕被人骂。。。。

#5楼[楼主]   回复  引用  查看    

2006-12-03 17:15 by 肖鹏      
@Dflying Chen
你说没看懂,那不是骂我!

#6楼   回复  引用    

2006-12-03 17:16 by 航天奇侠

什么23模式,就是不断增加中间层的设计思路而已。

#7楼   回复  引用  查看    

2006-12-03 17:24 by Dflying Chen      
@肖鹏
你误会了,不是说你写得不好,更不是骂你,而是我真的没看懂……
可能工作中用到的不多吧,还没有上升到这种高度,所以说需要学习啊。

#8楼   回复  引用  查看    

2006-12-03 17:27 by TerryLee      
@肖鹏
呵呵,可能刚才真有点生气,去向那位博主道歉去:)

#9楼   回复  引用  查看    

2006-12-03 17:40 by Dflying Chen      
@TerryLee
似乎他的评论已经没了……

#10楼   回复  引用  查看    

2006-12-03 18:16 by idior      
我来冒个泡, 不谈模式很多"年"~~~~~~~~~
呵呵

___
Idior说很多人没有注意到AnOperation这个方法
___
其实我这里的意思就是说使用factory method模式时,那个包含factory method的类往往不是一个专门的工厂,它只是提供了创建方法,它还有该类型所需要的其他方法也就是AnOperation。
___
那么Factory Method是不是可以有一个独立的Factory类与其对应呢?当然可以,而且恭喜你,如果你的独立的Factory类中包含几个Factory Method,你已经在使用Abstract Factory了。
___
这里的理解和我是一致的。


它们的区别还是如我在文章中所说
Factory Vs Abstract Factory -》 Inheritance Vs Composition
Abstract Factory 将创建方法单独拎出来做了一系列的类。演化过程也就根据这个思想。

———
没有Factory这个模式,大多数人提到Factory模式的时候,实际上指的是Factory Method。
———
确实如此,我在那篇文章也犯了这个错误。



#11楼   回复  引用  查看    

2006-12-03 20:35 by flyingchen      
分析的不错
帮兄弟顶一下!

#12楼[楼主]   回复  引用  查看    

2006-12-03 20:59 by 肖鹏      
一个DFlying Chen,一个Flying Chen,有意思,呵呵。这个名字有什么特别含义?陈飞?

#13楼   回复  引用  查看    

2006-12-05 09:33 by Kim Taehee      
心中有模胜无模,心中无模似有模!这个是我看设计模式来的体会。懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要,但他不是全部,并且离全部差很远!

#14楼   回复  引用  查看    

2006-12-05 09:37 by Kim Taehee      
我欣赏大家的是那份干工作的热情和对事物本质的孜孜不倦地追求,但是设计模式学习这个东西,我认为需要站在一个更高的角度去理解,不要注意其形,要注意其神,注意作者在提出设计模式这个东西时,希望学习的人达到的目的。世界本没有模式,做的人多了,讨论的人多了,他便是一种模式。期望和大家一起进步。

#15楼[楼主]   回复  引用  查看    

2006-12-05 11:17 by 肖鹏      
我想问问Kim,你理解设计模式的神是什么呢?形又是什么?作者提出希望达到的目的是什么?

#16楼   回复  引用  查看    

2006-12-08 15:57 by 冰火      
按照martin得说法,现在都不谈factory method了,也就是说过时了吧,呵呵

#17楼   回复  引用    

2007-07-15 23:06 by pp1982[未注册用户]
对于抽象工厂方法最好的例子就是ADO.net里的IConnection,IDbCommand,IDbDataReader接口的应用,这一系列的接口就是抽象的产品,而实际的产品就是SqlConnectiom+SqlCommand+SqlDataReader 或者 OleDbConnection+OleDbCommand+OleDbDataReader等等。实际的工厂就是和具体某种数据库相关的,比如SqlDbFacotry,通过所实现的抽象工厂的方法分别来创建SqlConnectiom,SqlCommand,SqlDataReader的实例(不过都是以抽象的产品--即三个接口作为返回的)。在客户代码里是使用抽象工厂的引用,而其引用所指向的实际工厂对象的实例则是可以通过简单工厂或工厂方法来创建都可以。客户代码通过抽象工厂的引用来调用方法,从而获得抽象产品类型的引用,但这些引用都是指向了某种实际类型产品的对象实例。

#18楼   回复  引用    

2007-08-07 20:08 by XX.Net[未注册用户]
SqlConnection+SqlCommand+SqlDataReader这一系列的时候是抽象工厂,是SQL/OleDB这一家族里的有关的成员,
SqlConnection+OleDbConnection这是工厂方法。是同一Connection类型的不同产品。

#19楼   回复  引用    

2009-07-04 16:47 by 99读书人网上书城[未注册用户]
新手学习ing!



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 580593




相关文章:

相关链接: