Factory Method

Also known as virtual constructor.

Problem

We need to decouple the behavior of an object from its creation. This might happen, for example, in a framework, where we can't anticipate the kind of objects we must create, but we can anticipate their behavior.

Solution

A factory method is a method that creates and returns new objects. A factory is a class containing one or more factory methods. In this context the types of objects created by the factory method are called products.

Structure

Sample Implementation

See:

Context.java

ConcreteFactoryA.java

ConcreteFactoryB.java

Examples

Parsing XML in Java

An XML parser reads an XML document and parses it into a tree structure that conforms to the Document Object Model (DOM) specification. There are many XML parsers: Saxon and Xalan to name a few.

Java uses the Factory Method pattern to hide the type of parser used:

Here's some sample context code:

String xmlFile = "mydoc.xml";
// obtain parser factory:
DocumentBuilderFactory factory =
   DocumentBuilderFactory.newInstance();
//obtain parser:
DocumentBuilder builder =
   factory.newDocumentBuilder();
// parse an xml document into a DOM tree:
Document doc =
   builder.parse(new File(xmlFile));

JDBC

Java uses the Factory Method pattern to decouple the behavior of executing SQL queries from the type of database used:

One might argue that the sstatic getConnection method of the DriverManager class is also a factory method.

Here's some sample code:

      String dbaseName = dbasePrefix + dbase;
      try {
         Class.forName(driverName);
         connection =
            DriverManager.getConnection(
               dbaseName, username, password);
      } catch (Exception e) { // dbase not found?
         System.err.println(
            "can't connect to " + dbaseName + " because " + e);
         connection = DriverManager.getConnection(
            dbaseName + ";create=true");
      }
      statement = connection.createStatement();

Generic Constructors

In C++ template parameters can represent constructors as well as classes, so generic constructors can be used to delay decisions about the types of products to create:

template<typename Product>
class GenericFactory
{
public:
   // generic constructor:
   Product* makeProduct() { return new Product(); }
};

In this case there is no need to introduce an abstract Product base class. Here is how a client creates a concrete product:

GenericFactory<ConcreteProductA> factory;
AbstractProduct* p = factory.makeProduct();

The same trick doesn't work in Java, however.

Commands as Products

The Command Processor pattern can be enhanced by providing an abstract base class for all control listeners that uses a factory method to create commands to be forwarded to the command processor. Concrete listeners only need to implement the factory method.

abstract class AbstractCommandFactory implements ActionListener {
   protected CommandProcessor cp;
   public void actionPerformed(ActionEvent ae) {
      AbstractCommand cmmd = makeCommand(ae.getLabel());
      commandProcessor.execute(cmmd);
   }
   protected AbstractCommand makeCommand(String label);
}

Views as Products

A generic listener for a view menu can use a factory method to create the needed view:

abstract class AbstractViewFactory implements ActionListener {

   public void actionPerformed(ActionEvent ae) {
      AbstractView view = makeView(ae.getLabel());
      view.setVisible(true);
   }
   protected AbstractView makeView(String label);
}

Slaves as Products

In the Master-Slave pattern the master uses a factory method to create slaves that perform sub-tasks:

interface Slave extends Runnable {

}

public abstract class Master {
   protected abstract Slave makeSlave();
   int slaveCount = 100;
   Slave[] slaves = new Slave[slaveCount];
   public void run() {
      // create slaves:
      for(int i = 0; i < slaveCount; i++) {
         slaves[i] = makeSlave();
      }
      // start slaves:
      for(int i = 0; i < slaveCount; i++) {
         slaves[i].start();
      }
      // wait for slaves to die:
      for(int i = 0; i < slaveCount; i++) {
         try {
            slaves[i].join();
         } catch(InterruptedException ie) {
               System.err.println(ie.getMessage());
         } finally {
            System.out.println(slaves[i].getName() + " has died");
         }
      }
      System.out.println("The master will now die ... ");
   }
}

Product Pools

Creating and destroying (garbage collecting) products can be expensive. An interesting variation of a factory pulls unused products from a pool. A delete method returns products to the pool:

abstract class PoolingFactory implements AbstractFactory {
   private Queue<AbstractProduct> pool = new LinkedList<AbstractProduct>();
   public AbstractProduct getProduct() {
      if (pool.size() == 0) {
         pool.add(makeProduct());
      }
      return pool.poll();
   }
   public void delete(AbstractProduct p) {
      pool.offer(p);
   }
}

Types as Objects

In the Types as Objects Pattern InstanceType plays the role of Factory and Instance plays the role of Product.

Factory Methods as Fields

Suppliers in Java 8