Factory Method - Programming in the Large with Design Patterns (2012)

Programming in the Large with Design Patterns (2012)

Chapter 8. Factory Method

Class inheritance and method overriding have long been used in object-oriented programming to change the behavior of a class. The Factory Method is a special case where the behavior changed is object creation.

Introduction

The standard way of creating an object is to instantiate a concrete class directly with the new operator:

SomeClass sc = new SomeClass();

One of the drawbacks of using the new operator to create an object is the need to specify the type of object to create. Specifically, it creates a dependency between your code and the class or type of object created. Sometimes a more general solution is needed, one that allows control over when an instance of an object is created but leaves open or delegates to another class the specific type of object to create. Decoupling object creation from object use results in code that is more flexible and extendable.

To illustrate, consider the following class PaymentService. Notice that PaymentService creates an instance of and calls methods on FinancialTrustCCP, a third-party credit card processing service.

PaymentService creates an instance of FinancialTrustCCP at line 7. This creates a dependency between the two classes that can lead to problems. For one, it is impossible to unit test PaymentService independent of FinancialTrustCCP. If FinancialTrustCCP is a third-party service connected to the global banking network, each test will create a transaction in the global banking network.

The current design also violates the open/closed principle. There is no way to extend the current solution to work with other credit card processing services without modifying the code.

These shortcomings in the design can be addressed by the Factory Method design pattern. The Factory Method design pattern delegates object creation to subclasses. Here is a new version of PaymentService where subclasses decide which concrete class for credit card processing to create:

The new design is more flexible. It decouples object creation from object use. The class PaymentService delegates responsibility for creating an instance of a credit card processing service to the factory method createCCPService(). PaymentService provides a default implementation ofcreateCCPService() but subclasses of PaymentService can override createCCPService() and substitute a different service. One practical benefit is test cases can substitute a mock object in place of the live credit card processing service FinancialTrustCCP. Here is an example test case that substitutes mock object MockCCPService for FinancialTrustCCP:

The Factory Method is one of several creational patterns. It uses inheritance and polymorphic methods to delegate responsibility for object creation to subclasses. Class inheritance and method overriding have long been used in object-oriented programming to change the behavior of a class. The Factory Method is a special case where the behavior changed is object creation.

Intent

One of the most important rules-of-thumb in software design is, “program to an interface, not an implementation”. This advice is probably most familiar in the context of calling operations on objects. You could write client code that accepts a LinkedList:

void clientCodeA(LinkedList list) {

for (int i=0; i < list.size(); i++)

. . .

}

However, if there is nothing about clientCodeA() that requires a LinkedList, it is usually better to program to a more abstract interface supported by various concrete collection classes:

void clientCodeB(Collection collection) {

for (int i=0; i < collection.size(); i++)

. . .

}

ClientCodeB() is better than clientCodeA() because clientCodeB() works with any concrete type that conforms to the abstraction Collection. clientCodeA() only works for LinkedLists.

The advice “program to an interface, not an implementation” also applies to object creation. You could create an object with the new operator:

However, the reference to concrete class SupportingClass at line 3 is an example of programming to an implementation. If there is nothing about clientCodeC that requires an instance of SupportingClass, it is usually better to program to an abstract interface that will result in the creation of an instance of SupportingClass or another type that is compatible with the client code.

What’s not so obvious is how to program to an interface when creating objects. That is precisely the problem solved by the Factory Method design pattern. The Factory Method Pattern “defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses” (Gamma 1995).

Here is one way of redesigning the previous code fragment to use the Factory Method design pattern:

In the revised code fragment, the overridable method createSupportingClass()is responsible for creating the object used at line 3. To change the type of object created at line 3 you would extend ClientCodeD and override createSupportingClass().

Notice that the revised solution also conforms to the open/closed principle. It is open for extension but closed for modification. You can change the type of object created at line 3 without altering the source code of ClientCodeD.

Solution

The Factory Method design pattern has four main components (see Figure 60). The class Creator declares a factory method createProduct(). createProduct() returns an object of type Product. Subclasses of Creator (ConcreteCreator in Figure 61) override the factory method to create and return a concrete instance of Product (ConcreteProduct in Figure 61).

Figure 61 Factory Method design pattern

The client code that calls the factory method and manipulates products (through the abstract interface Product) is usually contained in Creator. However, this isn’t a requirement of the design pattern. Client code may also reside outside the class with the factory method.

Sample Code

Example #1

Consider a hierarchy of classes for managing digital images where there is an abstract superclass Image that encapsulates features common to all image types and concrete subclasses for different image formats such as JPGImage for JPG images, PNGImage for PNG images, etc. Concrete subclasses contain logic for reading and writing image data for the image type they represent.

Given a file for one of the supported image types, you have to decide which concrete image class to instantiate (JPGImage or PNGImage). One option is to examine the filename suffix and hope it is appropriate for the file data. Another option is to examine the actual file data and look for the signatures of the different file formats in header data. This example shows how to organize such class creation logic using the Factory Method design pattern.

The example has two concrete product types (JPGImage and PNGImage) and two concrete creator types (ImageCreatorUsingFileExtensions and ImageCreatorUsingFileData):

Figure 62 One-to-many relationship between concrete creators and concrete products

createImage(String fileName) is the factory method. Notice that it is parameterized. The parameter is used to decide which concrete product to return. It takes the file name of the image and returns one of the concrete product types.

class Client {

public static void main(String[ ] args) {

// Create an instance of a concrete creator.

ImageCreator imageCreator = new ImageCreatorUsingFileExtensions();

clientCode(imageCreator);

}

static void clientCode(ImageCreator imageCreator) {

Image image1 = imageCreator.createImage("beach.jpg");

Image image2 = imageCreator.createImage("sunset.png");

// Process the images . . .

}

}

abstract class ImageCreator {

public abstract Image createImage(String fileName);

}

class ImageCreatorUsingFileExtensions extends ImageCreator {

public Image createImage(String fileName) {

if (fileName.endsWith("jpg"))

return new JPGImage(fileName);

else if (fileName.endsWith("png"))

return new PNGImage(fileName);

else

return null;

}

}

class ImageCreatorUsingFileData extends ImageCreator {

public Image createImage(String fileName) {

// Use file data to decide image type

. . .

}

}

abstract class Image {

private int [ ] [ ] pixels;

public int [ ][ ] getPixels() {

return pixels;

}

}

class JPGImage extends Image {

public JPGImage(String fileName) {

// Read image data from fileName

// and store in pixels matrix.

. . .

}

}

class PNGImage extends Image {

public PNGImage(String fileName) {

// Read image data from fileName

// and store in pixels matrix.

. . .

}

}

Example #2

Iteration in Java depends on the Factory Method design pattern. To see how, consider the following boilerplate code for iterating over the elements of a collection in Java:

Line 2 includes a call to iterator(), which is a factory method defined for the interface Collection. Concrete collection classes decide which concrete iterator to create and return.

Figure 63 shows the structure diagram for iteration in Java. Notice how it differs from the structure diagram in the previous example (Figure 62). In the previous example there is a one-to-many relationship between concrete creators and concrete products. With iteration in Java there is a one-to-one relationship between concrete collection classes and concrete iterators. Both are valid forms of the pattern.

Figure 63 Parallel class hierarchy for iteration in Java

Discussion

Most language libraries include a number of factory classes. I did a quick search of the javax package (a small subset of the JDK) and found 44 classes with the word “factory” in their name:

[burrise@babbage src]$ find javax -iname *factory*

javax/security/sasl/SaslClientFactory.java

javax/security/sasl/SaslServerFactory.java

javax/management/MBeanServerFactory.java

javax/management/remote/JMXConnectorServerFactory.java

javax/management/remote/JMXConnectorFactory.java

javax/swing/BorderFactory.java

. . .

What’s interesting is only a small number of these self-described factory classes use the Factory Method design pattern. Many of the classes found (and others such as java.util.Collections that create objects but don’t include the word “factory” in their name) create objects using simpler techniques that don’t offer all the flexibility of the Factory Method pattern. A few definitions should help clarify the difference between the Factory Method pattern and these other techniques for creating objects.

A factory class is any class with one or more creational methods. A creational method is any method that returns an object. The Factory Method design pattern describes a class with a creational method that:

1. is nonstatic

2. is virtual (can be overridden)

3. returns a base class or interface type

Factory Method is one type of creational method. All Factory Methods are creational methods but not all creational methods are Factory Methods.

Factory Method, as described in (Gamma, et al. 1995), is a design pattern. The other techniques for creating objects are better thought of as programming idioms.

What are these other techniques for creating objects? A common programming idiom for creating objects is to use a static factory method in place of a constructor. For example, Java’s Boolean class offers the static factory method valueOf(boolean b):

public class Boolean {

public static final Boolean TRUE = new Boolean(true);

public static final Boolean FALSE = new Boolean(false);

. . .

// Static factory method

public static Boolean valueOf(boolean b) {

return (b ? TRUE : FALSE);

}

}

A static factory method is a public static method that returns an instance of its containing class. Clients needing an instance of the wrapper class Boolean can call valueOf(boolean b) rather than one of Boolean’s constructors. The main advantages of using static factory methods in place of constructors are:

1. More descriptive names. In most programming languages, constructor names must be the same as the class name. This constraint doesn’t apply to static factory methods. They can be named to reflect their intent.

2. More control over object creation. With static factory methods a new object doesn’t have to be created each time the method is called. Immutable objects (e.g. Boolean) can be shared and mutable objects can be managed as a pool of reusable objects. Notice that the Singleton design pattern is essentially a static factory method where the policy is to create and reuse a single instance of the class.

Another programming idiom for creating objects is to define a factory class that does nothing but create objects. For example, all the methods defined for the class javax.swing.BorderFactory are dedicated to creating Border objects:

public class BorderFactory {

public static Border createLineBorder(Color color) {

. . .

}

public static Border createRaisedBevelBorder() {

. . .

}

. . .

}

For added flexibility, the static methods of a dedicated factory class may return a base class or interface type. For example, Border is an interface. Clients of BorderFactory are unaware of (and therefore loosely coupled to) the concrete type of object returned.

Related Patterns

Factory Method and Singleton are both creational patterns. The Singleton design pattern controls the number of instances of a class that are created. The Factory Method design pattern decouples object creation from object use.

The Iterator design pattern uses a factory method to return the appropriate concrete iterator.

Factory methods are often used with Template Methods. The Template Method design pattern defers steps in an algorithm to subclasses. One of the steps typically is object creation.