The Factory Method Pattern

The Factory Method Pattern

Introduction

The factory method pattern is one of the classical 23 patterns described by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides in their high-impact book Design Patterns: Elements of Reusable Object-Oriented Software.

They define the template method pattern as follows:

[Its intent is to] define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Gamma et al., 2003, p. 107

The factory method pattern makes use of inheritance and template methods for decoupling a so-called Creator from the concretely needed so called Products. Usually two parallel inheritance hierarchies for creators and products exist, with the factory method linking them.

As usual, relationships with other patterns exist:

  • Abstract factories (also called factories of factories) make often use of the factory method pattern.
  • The factory pattern as already stated makes use of the template method pattern.

Structure of the factory method pattern

Four participants make up the pattern:

  • The Product which abstracts from the concrete product(s) (either by interface or by abstract class).
  • The ConcreteProduct(s) which will be instantiated.
  • The Creator base class (abstract) or interface.
  • The hierarchy of ConcreteCreators which instantiate the ConcreteProducts by means of the factory method.

The following class diagram exemplifies the relationship between the participants.

Example

Let us consider a car. Cars have motors. We can define an abstraction of a car but at this point we don’t know yet which motor will be equipped to which concrete car. But we know a car has a motor and all cars use the motor for the same purpose. So, we can put the motor-using behavior (marked as “stuff” in the Car class) and the motor itself in the abstract class but we must defer the concrete creation until the specific car requirements are known. The abstract createMotor() will be overridden by the subclasses. Note that createMotor is a template method.

public abstract class Car {

	private Motor motor;
	
	public Car() {
		motor = createMotor();
	}
	
	protected abstract Motor createMotor();
	
	// stuff
}

Of course, the base class could create a default motor or return some null object. But we won’t consider this case.

Two types of motors exist: a fuel efficient one and a powerful one.

public class FuelEfficientMotor extends Motor {
	// efficiency, efficiency, efficiency
}

public class PowerfulMotor extends Motor {
	// speed, acceleration, speed
}

An ecological car will equip the FuelEfficientMotor and a racing car the powerful one.

public class EcoCar extends Car {
	@Override
	protected Motor createMotor() {
		return new FuelEfficientMotor();
	}
}

public class RacingCar extends Car {
	@Override
	protected Motor createMotor() {
		return new PowerfulMotor();
	}
}

The abstract class is decoupled from the concrete motors, the concrete subclasses are not, which is not a big problem per se because the motor type is definitory for the car type. Should the necessity for a second ecological car type arise which has a different motor but retains the same state and behavior as the first model, sub-classing would be the answer. This practice could lead to many classes which can make the application confusing and thus hard to maintain. Usage of a parametrized factory method alleviates to some extent the problem.

public enum MotorType { ECOLOGICAL, POWERFUL };

protected Motor createMotor(MotorType motorType) {
	return switch (motorType) {
	case ECOLOGICAL -> new FuelEfficientMotor();
	case POWERFUL -> new PowerfulMotor();
	default -> throw new IllegalArgumentException();
	};
}

A better approach altogether might be the usage of dependency injection.

Factory Methods vs. Factory Method Pattern

We have to make an important distinction at this point between simple factories (sometimes also called factory methods) and the factory method pattern. Simple factories are usually static methods which return a fully configured object. You can also parametrize them. While they don’t offer the flexibility of the factory method pattern they can be used for decoupling. Consider the following (somewhat forced) example:

public class SomeService { }

public class Something {
	public Something(SomeService someService) {}
}

public class SomethingElse {
	public SomethingElse(Something something) {}
}

A client wants to work with SomethingElse but in order to instantiate it, it must deal with its other dependencies which are needed: Something and SomeService. This leads to a tight coupling. Creating an instance of SomethingElse can be transferred to a static factory (method).

public class SimpleFactory {

	public static final SomethingElse createSomethingElse() {
		SomeService someService = new SomeService();
		Something something = new Something(someService);
		SomethingElse somethingElse = new SomethingElse(something);
		return somethingElse;
	}
}

While this strategy introduces a new type and thus a new dependency for the client, he does not have to deal with SomeService and Something anymore (except the case these dependencies are really needed). Putting it in plain text: the Client doesn’t have to import SomeService and Something anymore, instead he can use the SimpleFactory.

public class Client {
	private final SomethingElse somethingElse;

	public Client() {
		somethingElse = SimpleFactory.createSomethingElse();
	}
}

Real-life examples of factory method patterns

Factories are very common. I’ll consider a single example here: the method of(E e) of the EnumSet class.

public static < E extends Enum< E >> EnumSet< E > of(E e) {
        EnumSet< E > result = noneOf(e.getDeclaringClass());
        result.add(e);
        return result;
}

At the first glance it does not do much: it creates an empty EnumSet by calling noneOf – another factory – adds the passed element to it and returns the result. So, by using this method you have one row instead of two, and you could have called directly the constructor (well, not really because it has only package visibility). But only when you have a look at noneOf(Class<E> elementType) you realize the necessity of a method for encapsulating all the gory details.

A good example for the factory method pattern is the BeanFactory of the Spring Framework.


References

Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (2003). Design Patterns. Delhi, India: Pearson Education.


You might also like the following articles:

Petre Sora

Petre Soras Interessen sind vielfältig und befinden sich an der Schnittstelle zwischen Mensch und Informationstechnologie. Als studierter Psychologe und Software Engineer war er knappe sechs Jahre als Java-Entwickler in mehreren Unternehmen tätig. Mit der Gründung der Rezensionsplattform nososo hat er sich entschieden eigene Wege zu gehen. Petre ist als Rezensent und Verfasser von Artikeln für nososo tätig.

Schreibe einen Kommentar