Design Patterns – Creational Patterns – Simple Factory

Galagans are an insectoid alien species from Dark Space, where they inhabit a planet of the same name. They fly insectoid organic-robotic spacecraft and are often seen in an armada. They are obsessed with attacking planet Earth, only to be thwarted by Earth’s agency called United Galaxy Space Force (aka UGSF) and their gifted space warriors piloting powerful spacecrafts.

Galagans have 4 different space-crafts Blue, Purple, Red and Gyaruboss. These space-crafts have different armour strengths and attack capabilities, the common capabilities are that they can all shoot and they can do a Kamikaze attack where they intentionally try to collide with the UGSF Spacecraft.

Tasked with writing a software application that can build these spacecrafts, the Galagan Software Company (GSC) designs the below UML to represent the Galagan Ship Hierarchy.

Galagan Ship UML

Ship-workshop sends out ships with a coating of paint which greatly improves stealth.

public class ShipWorkshop {

    public GalaganShip buildGalaganShip(String shipType) {

        // For flexibility, we will code to an interface/abstract class and not a concrete type.
        GalaganShip galaganShip;

        // Based on the type of ship, we will instantiate a concrete Ship and
        // assign to the GalaganShip instance variable.
        if ("RED".equals(shipType)) {
            galaganShip = new RedShip();
        } else if ("BLUE".equals(shipType)) {
            galaganShip = new BlueShip();
        } else if ("PURPLE".equals(shipType)) {
            galaganShip = new PurpleShip();
        } else if ("GYARUBOSS".equals(shipType)) {
            galaganShip = new GyarubossShip();
        } else {
            throw new IllegalArgumentException("Unsupported Ship Type");
        }

        // Apply stealth paint
        galaganShip.paint();

        return galaganShip;

    }
}

GSC understands that this is a critical application and spends a lot of time and money to test thoroughly and deploys the application to production.

After a number of defeats at the hands of the UGSF, High Command directs the Galagan R&D department to develop a new ship with far greater capabilities than the previous ones and wants the Workshop to be prepared for new variants.
GSC relooks at the application design to see if introducing new ship variants would cause any issues and realizes that the ShipWorkshop needs to be modified there by violating the “Closed for Modification” principle of Object Oriented Design. GSC now has to spend a lot of time and money in re-testing the Ship Workshop since there will be a modification. To teach the software designer a lesson, GSC sends him on a ship to face the mighty UGSF.

Another look at the design to solve this problem, GSC falls back on OO Design Principles for clues and identifies aspects that vary and those that remain the same. In this case, pulling out the concrete class instantiation from buildGalaganShip method into a type would solve the problem. GSC names this Type as SimpleGalaganShipFactory which is only going to worry about how to create the ships and if any other application would need to create an object of Type GalaganShip this is the Factory to come to.

public enum SimpleGalaganShipFactory {

    INSTANCE;

    public GalaganShip createGalaganShip(final String shipType) {
        GalaganShip galaganShip;

        // Based on the type of ship, we will instantiate a concrete Ship and
        // assign to the GalaganShip instance variable.
        if ("RED".equals(shipType)) {
            galaganShip = new RedShip();
        } else if ("BLUE".equals(shipType)) {
            galaganShip = new BlueShip();
        } else if ("PURPLE".equals(shipType)) {
            galaganShip = new PurpleShip();
        } else if ("BOSS".equals(shipType)) {
            galaganShip = new GyarubossShip();
        } else {
            throw new IllegalArgumentException("Unsupported Ship Type");
        }

        return galaganShip;
    }

}


The ShipWorkshop now uses this Factory to build the Galagan ships and is free from any concrete dependencies.

public class ShipWorkshop2 {

    public GalaganShip buildGalaganShip(String shipType) {

        // Delegate the Ship creation to the Factory. No more concrete instantiations here.
        GalaganShip galaganShip = SimpleGalaganShipFactory.INSTANCE.createGalaganShip(shipType);

        // Apply stealth paint
        galaganShip.paint();

        return galaganShip;

    }
}
If you know that this plot is from the famous Atari game GALAXIAN, you had an awesome childhood :-).

The Simple Factory is not a Design Pattern but a programming idiom. You might have a question, what advantage you would gain by pulling the concrete class instantiation from one class into another. Well, ShipWorkshop was the only client using these concrete instances. Imagine, you had multiple other places where you require an instance of the GalaganShip Type. All these places would have the same piece of code and would have to be modified when a new GalaganShip is introduced.

All Code is available @ https://github.com/roshanvinil89/learning.git