Factory Method

José Alexander Valladares
4 min readJul 4, 2021

Introduction

The first method to learn by many. A creational pattern, because it provides flexibility and reuse of code at the object creation. Lest see the definition by the book 📖

Is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.

To put it in other words. This DP suggests that a class should be responsible for creating different types of objects that have the same interface. But… why should we do that?

Problem

Let’s put an example of when you use this DP. Imagine that you’re creating a car simulation application. The first version of your app can only handle gas engines, so the bulk of your code lives inside the GasCar class.

After a while, you need to start working on your simulation for electric engines. At present, most of your code is coupled to the GasCar class. Adding an ElectricCar into the app world requires a lot of changes in code. Moreover, if later you decide to add another type of engine to the app, you will probably need to make a lot of work again.
By working like this you will have a lot of unnecessary scenarios with conditions that switch the app behavior depending on the class of engine.

Solution

It suggested that you replace direct method construction calls (the ones with the new) with a call to the factory method. The class Car is in charge of creating multiple type instances with the new operator. Objects that are created in a factory method are often referred to as products.

The use of subclasses can override the method and change the returned type of the factory method.

Now is possible to override the factory method in a subclass and return different types of engines. But there is a slight limitation, in order to return different types of products is necessary to implement an interface or class to link the Engines.

All products share the same interface.

Now, both GasEngine and ElectricEngine implement the interface Engine that declares the method startEngine. Each class implements this method differently: gas engines use combustibles to start, while electric engines use energy to work. The factory method inside GasCar returns gas engines objects, whereas the ElectricCar returns electric engines objects. The moment both inherit from a shared interface it’s possible to return products of the type Engine. The client (factory method) treats all the products as abstract Engine.

Structure

  1. The Product declares the interface, which is common to all objects that can be produced by the creators and subclasses.
  2. The Concrete Products are different implementations of the product interface.
  3. The Creator class declares the factory method that returns new product objects.
  4. Concrete Creators override the base factory method so it returns a different type of product.

Code step by step

Step 1: Create the interface Engine.

public interface Engine {
void startEngine();
}

Step 2: Create classes that implement the Engine interface and its methods.

Gas Engine class:

public class GasEngine implements Engine {
@Override
public void startEngine() {
System.out.println("Gas engine starting...");
}
}

Electric Engine class:

public class ElectricEngine implements Engine {
@Override
public void startEngine() {
System.out.println("Electric car starting...");
}
}

Step 3: Create a Car abstract class.

public abstract class Car {
public abstract Engine createEngine();

// Start simulation
public void setUpCarSimulation(){
Engine e = createEngine();
e.startEngine();
}
}

Step 4: Create classes that extends Car abstract class.

Gas Car class:

public class GasCar extends Car {
@Override
public Engine createEngine() {
return new ElectricEngine();
}
}

Electric Car class:

public class ElectricCar extends Car {
@Override
public Engine createEngine() {
return new GasEngine();
}
}

Step 5: Start the simulation for both type of cars

public class Simulation {
public static void startSimulation(){
// Create a new instance of GasCar
Car gasCar = new GasCar();
// Create a new instance of ElectricCar
Car electricCar = new ElectricCar();

// Setup simulation car and run simulation
System.out.println("Preparing and staring simulation for gas car");
gasCar.setUpCarSimulation();
System.out.println("Simulation done");
System.out.println("Preparing and staring simulation for electric car");
electricCar.setUpCarSimulation();
System.out.println("Simulation done");
}
}

Results from simulation:

Preparing and staring simulation for gas car.
Electric car starting...
Simulation done.
Preparing and staring simulation for electric car.
Gas engine starting...
Simulation done.

The Pros

  • You avoid tight coupling between the creator and the concrete products.
  • Single Responsibility Principle. You can move the product creation code into one place in the program, making the code easier to support.
  • Open/Closed Principle. You can introduce new types of products into the program without breaking the existing client code.

The Cons

  • The code may become more complicated since you need to introduce a lot of new subclasses to implement the pattern. The best-case scenario is when you’re introducing the pattern into an existing hierarchy of creator classes.

References

  • Alexander Shvets, A. S. (2021). Dive into design pattern (v2021–2.29 ed. ed.).

--

--

José Alexander Valladares
0 Followers

I'm software developer striving to become better at the craft.