WizardWu 編程網

一位台灣的工程師,接觸 .NET 逾十年,近年研究 SQL Server、Performance Tuning、手機應用

博客园 首页 新随笔 联系 订阅 管理

本帖介绍 Simple Factory (简单工厂)、Factory Method (工厂方法) 这两种设计模式,以及他们和变形金刚的关系。

--------------------------------------------------------
本帖的示例下载点:
https://files.cnblogs.com/WizardWu/090618.zip
(执行本示例,需要 VS 2008 或 IIS,不需要数据库)
--------------------------------------------------------

 

Simple Factory Pattern (简单工厂模式)


特性:

  • 把类的实例化工作,集中到一个「工厂类」去处理,亦即将 new instance 的工作,都交给一个「工厂」去处理,而不要分散写在各个类中。
  • 客户端程序,与创建实例 (对象) 的工作必须隔离,亦即「解耦」,客户端程序只要专注于自己的业务逻辑。适用于客户端程序在开发过程中,尚无法预知要创建的具体类型。
  • 产品具体的实现能和客户端隔离,便于事后抽换。

Simple Factory Pattern (简单工厂模式)、Factory Method Pattern (工厂方法模式),在实作的代码中,有时很难明确去界定此二者。Simple Factory 的特性,如前所述,在于将创建实例 (new instance) 的工作,集中由特定的一个「工厂类」来处理,避免写在各个类中,以方便日后添加新功能,和修改既有的功能。

如下「进口水果」的代码,为 O'Reilly 的「C# 3.0 Design Patterns」这本书籍 [1] 第五章的 Factory Method 示例。乍看之下,我觉得它比较像 Simple Factory Pattern,因其仍将创建实例,和部分逻辑判断的工作,都集中在一个 工厂类 (Creator1 类) 去处理,导致日后要添加新功能 (多引进一个国家的水果),或要修改判断「进口月份」的逻辑时,仍要修改 server-side 的这个「工厂类」,而无法只修改 client-side 的 Page_Load 方法,违背了「开放-封闭」原则。

但这个示例,要实例化哪个类型,是由「工厂类」以及客户端 (水果店主人) 的 Page_Load 方法,共同决定的。透过 IProduct 接口,看似隔离了客户端程序、具体 Product 的依赖关系,但客户端程序仍有创建对象的决定权,因此其与创建实例 (对象) 的工作并未真正隔离。

 

SimpleFactory.aspx.cs

 

 


图 1 Sybase PowerDesigner 绘制的「进口水果」示例的 Class Diagram

 

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

 

Factory Method Pattern (工厂方法模式)


特性:

  • 由子类来决定要具体实例化哪种类型。这些子类实现了某个共通的接口,或继承自某个共用的抽象类。
  • 让一个类的实例化,延迟到其子类。
  • 由客户端程序,来决定要创建哪些工厂类型。

上述特性的第一点,所提到的子类,如同下方示例里的「博派Factory」类、「狂派Factory」类。

上述特性的第三点,Factory Method 和 Simple Factory 刚好相反。Factory Method 把 Simple Factory 中「工厂类」的逻辑判断,移到客户端来进行。日后若想添加、修改功能,原本 Simple Factory 是要修改「工厂类」的,但 Factory Method 变成要修改客户端程序,但也改善了 Simple Factory 的缺点,亦即不用再冒险修改原本已可正常工作的 server-side「工厂类」,而只要改 client-side 的 Page_Load 方法,符合了「开放-封闭」原则。

Factory Method 的实现方式有很多种,但原则为,先用一个抽象类或接口,当作定义 (如下方示例的 IFactory),并留下抽象方法而不实作 (如下方示例的 createTransformer 方法)。要延迟到子类,由子类来决定要实例化哪种类型 (如下方示例的「博派Factory」和「狂派Factory」这两个子类)。

 

FactoryMethod.aspx.cs

 

 



图 2 Sybase PowerDesigner 绘制的「变形金刚 - 工厂方法模式」Class Diagram

 

以后引进新产品 (堕落金刚) 时,我们不需要冒险修改既有的「工厂类」,而只要添加新的「产品类」、新的「工厂类」,最后由 IFactory 的子类,以及客户端程序 (Page_Load 方法),来决定要创建哪些具体类型;整个架构变成只有「扩展」的变化,而不再有「修改」的变化。此外,若要修改旧功能,如:「狂派」类,要加入组合成「大力神」的功能时,也只需要修改既有的「狂派」类即可。


Factory Method Pattern 并无固定的实现方式,上述两个示例,仅为其中一种实现方式,若参考一些 Java 的论坛、书籍、文件,还能找到更多的变化应用 [7], [8]。


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

相关书籍:

[1] C# 3.0 Design Patterns, Judith Bishop, O'Reilly
http://oreilly.com/catalog/9780596527730/
http://www.oreilly.com.cn/book.php?bn=978-7-111-25080-7

[2] 大话设计模式 (繁体中文翻译本), 程杰 着, 清华大学出版社
http://www.cnblogs.com/cj723/archive/2009/03/12/1409359.html

[3] Head First 设计模式, Freeman, O'Reilly
http://oreilly.com.cn/book.php?bn=978-7-5083-5393-7

[4] 设计模式 - 基于 C# 的工程化实现及扩展, 王翔 着, 电子工业出版社
http://www.china-pub.com/129880

[5] Design Patterns 于 Java 语言上的实习应用 (繁体中文翻译本), 结城浩 着, 博硕文化出版社

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

相关资料:

[6] Simple Factory 模式,作者: caterpillar (繁体中文)
http://caterpillar.onlyfun.net/Gossip/DesignPattern/SimpleFactory.htm
http://www.javaworld.com.tw/jute/post/view?bid=44&id=24830&sty=1&tpg=1&age=-1

[7] Factory Method 模式,作者: caterpillar (繁体中文)
http://caterpillar.onlyfun.net/Gossip/DesignPattern/FactoryMethod.htm
http://www.javaworld.com.tw/jute/post/view?bid=44&id=24993&sty=1&tpg=1&age=-1

[8] 史帝芬心得筆記 -- Factory Method Pattern (繁体中文)
http://my.so-net.net.tw/idealist/Patterns/FactoryMethod.html

[9] .NET设计模式(5):工厂方法模式(Factory Method)
http://www.cnblogs.com/Terrylee/archive/2006/01/04/310716.html

[10] Design Pattern - 真 OO无双
http://www.cnblogs.com/oomusou/category/82066.html

[11] .Net Go2 OO (繁体中文)
http://netgo2oo.blog.ithome.com.tw/

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

posted on 2009-06-18 03:20  WizardWu  阅读(3303)  评论(17编辑  收藏  举报