JavaScript must be enabled in order for you to view this page. However, it seems JavaScript is either disabled or not supported by your browser. To view this page, enable JavaScript by changing your browser options, then Try again! .

文章目录
 
我的论坛
Google 网上论坛 Beta 版
Do Best Developer
访问此论坛

简单工厂模式(Simple Factory)

solo L
发布日期:2006年12月01日,更新日期:2006年12月01日

写在前面

如果您还没有阅读面向对象设计(Object-Oriented Design),那么我建议您从那里开始。

回页首

名称

简单工厂模式(Simple Factory)

回页首

结构

简单工厂模式的结构图

这里有三个参与者,抽象产品(Product)、工厂(Creator)和具体产品(ConcreteProduct)。客户只会看到工厂和抽象产品。

我们使用这个模式的一个主要的目标就是对客户隐藏具体的产品。从客户的角度出发来看这个模式它是符合开闭原则的,即我们可以为系统添加新的具体产品而不影响客户。但从工厂的角度出发来看这个模式它又不太符合开闭原则,因为工厂要知道生产具体产品的细节,也就意味着添加新的具体产品时我们要修改工厂。不过在Java中我们可以采用一些技巧来缓解这个问题。这一点将会在介绍XMLReaderFactory示例时涉及到,这是一个应用很普遍的技巧。

我们使用这个模式的另一个目标就是对客户隐藏创建具体的产品的过程。在这种情形下客户需要向工厂提供一些信息,然后工厂根据这些信息为客户创建合适的产品。

注意:其中的factory():Product方法是静态的。

静态工厂方法有时候还可以多于一个。

回页首

示例

如果您在学习 Java SE 或 Eclipse 的过程中发现了适合这里的示例,希望能告诉我们。我们会在团队中感谢给予我们帮助的朋友们。

示例 1

这个示例源于Java SE。您可以查阅org.xml.sax.helpers.XMLReaderFactory。

XMLReaderFactory

您应该很容易从图中区分出来抽象产品(XMLReader)、工厂(XMLReaderFactory)和具体产品(SAXParser)三个参与者。值得注意的是实际中的SAXParser和XMLReader之间的关系并不象图中所画的那样,这里做了简化。

XMLReaderFactory中有两个工厂方法:

静态方法createXMLReader():XMLReader中使用了一个技巧(Java中的反射),这使得在添加新的具体产品时不必修改工厂。该方法试图使用1、2和3这三种方式来得到class name,这是非常普遍的。这样处理使在添加新的具体产品时只要修改系统属性org.xml.sax.driverMETA-INF/services/org.xml.sax.driver就可以了。

  1. If the system property org.xml.sax.driver has a value, that is used as an XMLReader class name.
  2. The JAR "Services API" is used to look for a class name in the META-INF/services/org.xml.sax.driver file in jarfiles available to the runtime.
  3. SAX parser distributions are strongly encouraged to provide a default XMLReader class name that will take effect only when previous options (on this list) are not successful.
  4. Finally, adapt any SAX1 parser.

静态方法createXMLReader(className:String):XMLReader使用了一个className,这使得客户可以决定使用什么具体产品。

回页首

变体

如果您在学习 Java SE 或 Eclipse 的过程中发现了适合这里的变体,希望能告诉我们。我们会在团队中感谢给予我们帮助的朋友们。

变体 1

具有多个抽象产品参与者。结构图如下:

具有多个抽象产品参与者的简单工厂模式

这个示例源于Java SE。您可以查阅java.lang.management.ManagementFactory。这里做了简化,完整的实现中除了简单工厂模式之外,还使用了桥接模式(Bridge)和单例模式(Singleton)。

ManagementFactory

变体 2

将工厂和抽象产品两个参与者合并,让抽象产品来生产一个具体的产品。

这个示例源于Java SE。您可以查阅java.text.NumberFormat。其中NumberFormat既是抽象产品又是工厂而DecimalFormat是具体产品。

NumberFormat

该变体的其它示例:

1、在java.text包中还有一个极为相似的示例,就是DateFormat,其中DateFormat是抽象产品和工厂而具体产品则是SimpleDateFormat。

变体 3

将抽象产品这个参与者去掉,然后再将工厂和具体产品两个参与者合并。

这个示例源于Eclipse 3.2。您可以查阅org.eclipse.jdt.core.dom.ASTParser。

ASTParser

变体 4

产品的层次结构可以很复杂。

这个示例源于Eclipse 3.2。您可以查阅org.eclipse.update.core.model.FeatureModelFactory。

FeatureModelFactory
回页首

相关模式

工厂方法模式(Factory Method)

抽象工厂模式(Abstract Factory)

单例模式(Singleton)

桥接模式(Bridge)

关于作者
solo L 一位有些理想主义的软件工程师,创建了solol.org。他常常在这里发表一些对技术的见解。