Hi Graham,
-My question is which entity should be responsible for deciding which concrete factory object
should be instantiated.
An abstract factory is a class whose purpose is to instantiate a family of classes -- an object
maker. In its simplest form, there is one "factory" class used to instantiates subclasses.
The
entity responsible for deciding which concrete factory object to instantiate is usually
a system property. The Abstract factory class reads this property and decides at runtime which
class to instantiate. This allows the factory to change its implementation without necessitating a
recompile.
- Does it matter that the AbstractFactory may then acquire some implementation awareness to achieve
this?
If the concrete class to be instantiated is decided at runtime, the factory is spared from
the awareness of different implementations. This is very important and is in fact the main
principle behind this pattern. Its important to note here that the Abstract Factory Pattern along
with a few other patterns is a part of bigger design approach called Protected variations(Larmnan).
In Larman's words PV is:
Identifying points of predicted variation and creating a stable interface around them.
This approach lets you change or parameterize a system�s behavior through external logic
expressions. The system is protected from the impact of logic variations by externalizing the logic,
reading it in (for example, rules), and using an interpreter.
If you understand this, you can easily realize the importance of Factory not being aware of
the concrete implementations.
Lets consider an example.
The
Java API for XML Processing (JAXP) enables applications to parse and transform XML documents
independent of a particular XML processing implementation. This ability is a direct result of
employing an abstract factory design pattern.
The JAXP specification does not provide any implementation. Vendors provide the actual
implementation (i.e. concrete classes that implement the interfaces or extend the abstract classes)
of the specification;
The factory implementation that is used is controlled by the
javax.xml.style.TransformFactory
runtime property (the deciding entity). This allows the parser to change without necessitating
a recompile.
A client code using SAXParserFactory may look like this.
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
This program is unaware of any specific implementation of SAXParser. It simply gets a new instance
of factory and requests the factory to provide a SAXParser.
Here's the source for SAXparserFactory class
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
source for SAXParserFactory .java
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public static SAXParserFactory newInstance()
throws FactoryConfigurationError
{
try {
return (SAXParserFactory) FactoryFinder.find(
/* The default property name according to the JAXP spec */
"javax.xml.parsers.SAXParserFactory",
/* The fallback implementation class name */
"org.apache.crimson.jaxp.SAXParserFactoryImpl");
} catch (FactoryFinder.ConfigurationError e) {
throw new FactoryConfigurationError(e.getException(),
e.getMessage());
}
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
source for FactoryFinder.java
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
static Object find(
String factoryId, String fallbackClassName)
throws ConfigurationError
{
ClassLoader classLoader = findClassLoader();
// Use the system property first
try {
String systemProp =
System.getProperty( factoryId ); if( systemProp!=null) {
debugPrintln("found system property" + systemProp);
return newInstance(systemProp, classLoader);
}
} catch (SecurityException se) {
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Here the factory looks at the system property to decide which concrete factory implementation
is required and instantiates it.
Hope that helps,
Ali.