简单工厂模式(Simple Factory)
写在前面
如果您还没有阅读面向对象设计(Object-Oriented Design),那么我建议您从那里开始。
名称
简单工厂模式(Simple Factory)
结构
这里有三个参与者,抽象产品(Product)、工厂(Creator)和具体产品(ConcreteProduct)。客户只会看到工厂和抽象产品。
我们使用这个模式的一个主要的目标就是对客户隐藏具体的产品。从客户的角度出发来看这个模式它是符合开闭原则的,即我们可以为系统添加新的具体产品而不影响客户。但从工厂的角度出发来看这个模式它又不太符合开闭原则,因为工厂要知道生产具体产品的细节,也就意味着添加新的具体产品时我们要修改工厂。不过在Java中我们可以采用一些技巧来缓解这个问题。这一点将会在介绍XMLReaderFactory示例时涉及到,这是一个应用很普遍的技巧。
我们使用这个模式的另一个目标就是对客户隐藏创建具体的产品的过程。在这种情形下客户需要向工厂提供一些信息,然后工厂根据这些信息为客户创建合适的产品。
注意:其中的factory():Product方法是静态的。
静态工厂方法有时候还可以多于一个。
示例
如果您在学习 Java SE 或 Eclipse 的过程中发现了适合这里的示例,希望能告诉我们。我们会在团队中感谢给予我们帮助的朋友们。
示例 1
这个示例源于Java SE。您可以查阅org.xml.sax.helpers.XMLReaderFactory。
您应该很容易从图中区分出来抽象产品(XMLReader)、工厂(XMLReaderFactory)和具体产品(SAXParser)三个参与者。值得注意的是实际中的SAXParser和XMLReader之间的关系并不象图中所画的那样,这里做了简化。
XMLReaderFactory中有两个工厂方法:
静态方法createXMLReader():XMLReader中使用了一个技巧(Java中的反射),这使得在添加新的具体产品时不必修改工厂。该方法试图使用1、2和3这三种方式来得到class name,这是非常普遍的。这样处理使在添加新的具体产品时只要修改系统属性org.xml.sax.driver或META-INF/services/org.xml.sax.driver就可以了。
- If the system property
org.xml.sax.driverhas a value, that is used as an XMLReader class name. - 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.
- 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.
- Finally, adapt any SAX1 parser.
静态方法createXMLReader(className:String):XMLReader使用了一个className,这使得客户可以决定使用什么具体产品。
变体
如果您在学习 Java SE 或 Eclipse 的过程中发现了适合这里的变体,希望能告诉我们。我们会在团队中感谢给予我们帮助的朋友们。
变体 1
具有多个抽象产品参与者。结构图如下:
这个示例源于Java SE。您可以查阅java.lang.management.ManagementFactory。这里做了简化,完整的实现中除了简单工厂模式之外,还使用了桥接模式(Bridge)和单例模式(Singleton)。
变体 2
将工厂和抽象产品两个参与者合并,让抽象产品来生产一个具体的产品。
这个示例源于Java SE。您可以查阅java.text.NumberFormat。其中NumberFormat既是抽象产品又是工厂而DecimalFormat是具体产品。
该变体的其它示例:
1、在java.text包中还有一个极为相似的示例,就是DateFormat,其中DateFormat是抽象产品和工厂而具体产品则是SimpleDateFormat。
变体 3
将抽象产品这个参与者去掉,然后再将工厂和具体产品两个参与者合并。
这个示例源于Eclipse 3.2。您可以查阅org.eclipse.jdt.core.dom.ASTParser。
变体 4
产品的层次结构可以很复杂。
这个示例源于Eclipse 3.2。您可以查阅org.eclipse.update.core.model.FeatureModelFactory。
