The factory method pattern

In the simplest terms, a factory method is a method which creates objects and lets a class defer instantiation to its subclasses.

It may either be implemented directly in a class (and optionally overriden in its children) or specified in an interface (and implemented by classes which use it).

It helps decouple code from concrete implementations of interfaces, making it more flexible to change and solves problems related to deferring class instantiation, giving subclasses the ability to define the way an object is created.

Usage example – subclassing

You have two types of Weapons Lasers and Rockets:

interface Weapon {
    String shoot();
}
class Laser implements Weapon {
    @Override public String shoot() {
        return "lasers!";
    }
}
class Rocket implements Weapon {
    @Override public String shoot() {
        return "rockets!";
    }
}

You want to create two types of spaceships – a Frigate (equipped with Lasers) and a Destroyer (equipped with Rockets), so that you can make them shoot their weapons:

abstract class Spaceship {
    abstract protected Weapon createWeapon();
    public String shootWeapon() {
        Weapon Weapon = createWeapon();
        return "Firing my ".concat(Weapon.shoot());
    }
}
class Frigate extends Spaceship {
    @Override protected Weapon createWeapon() {
        return new Laser();
    }
}
class Destroyer extends Spaceship {
    @Override protected Weapon createWeapon() {
        return new Rocket();
    }
}

That abstract createWeapon() function is the factory method. It creates an instance of a class implementing the Weapon interface – the choice of the class is up to the subclasses extending the Spaceship class.

Finally, we can interact with the Spaceships:

class SpaceWarExample {
    public static void main(String[] args) {
        Spaceship Frigate = new Frigate();
        System.out.println(Frigate.shootWeapon());
        Spaceship Destroyer = new Destroyer();
        System.out.println(Destroyer.shootWeapon());
    }
}

…Which gives us the output:

Firing my lasers!
Firing my rockets!

Usage example – using factory classes

It is possible to take the factory method one step further and extract the method into its own factory class. Imagine that you have two types of Spears Light Spears and Heavy Spears:

interface Spear {
    String throwAtNearestEnemy();
}
class HeavySpear implements Spear {
    @Override public String throwAtNearestEnemy() {
        return "Throwing a heavy spear...";
    }
}
class LightSpear implements Spear {
    @Override public String throwAtNearestEnemy() {
        return "Throwing a light spear...";
    }
}

You want to have a Spear Thrower that will be able to throw both a Heavy Spear and a Light Spear at the nearest enemy. To achieve that, you can create factory classes for the Spears:

interface SpearFactory {
    Spear createSpear();
}

class HeavySpearFactory implements SpearFactory {
    @Override public Spear createSpear() {
        return new HeavySpear();
    }
}

class LightSpearFactory implements SpearFactory {
    @Override public Spear createSpear() {
        return new LightSpear();
    }
}

These factories are the key to this implementation of the factory method pattern. Notice that the factories’ sole purpose is creating Spears. You can now define a SpearThrower:

class SpearThrower {
    public String useSpear(SpearFactory SpearFactory) {
        final Spear spear = SpearFactory.createSpear();
        return spear.throwAtNearestEnemy();
    }
}

The SpearThrower is independent of the Spears he uses. Each time you want him to use a Spear, you pass a SpearFactory to his useSpear() function, which then provides the relevant Spear. Another option would be to pass a SpearFactory in the SpearThrower's constructor.

We can now use the SpearThrower in our application:

class SpearThrowerExample {
    public static void main(String[] args) {
        SpearThrower spearThrower = new SpearThrower();
        System.out.println(spearThrower.useSpear(new HeavySpearFactory());
        System.out.println(spearThrower.useSpear(new LightSpearFactory()));
    }
}

The code above will output:

Throwing a heavy spear...
Throwing a light spear...

You can then add more types of Spears (e.g. a Weightless Spear) and the SpearThrower will be able to use them right away – there will be no need of modifying the SpearThrower's code. Let’s imagine someone wrote a library called ExtendedSpearTypes, which contains a WeightlessSpear and a WeightlessSpearFactory. We can include the library in our application and make a call like so, without making major changes to our core code:

spearThrower.useSpear(new WeightlessSpearFactory())

This way, the coupling exists on such a low level of abstraction that adding or removing new Spear type logic is trivial.

Notice, also, that this implementation is just one step away of becoming the Abstract Factory pattern – a pattern which could be described as a factory of factories. Both of them utilize the concept of a Factory class, the difference being that here our factory class only produces one instance of a desired interface implementation, instead of many related instances.

Daniel Frąk Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *