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.

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

Design Patterns- Creational – Builder Pattern

In 2013, Dave Hakkens a Dutch designer came up with a concept of making an open source modular smart phone named Phonebloks. By attaching individual third party components called bloks to a main board, a user can create his/her own personalized smart phone. These bloks can be snapped onto the main board like Lego bricks. As a result, instead of replacing an entire phone when say the screen is damaged or when the camera is broken or has become obsolete, the user can replace just the damaged or obsolete blok.

Lets assume that you are required to write a software to build these smart phones. Customers would give their initial configuration of their personalized Phoneblok, For example:- Some customers would want a big Nikon front facing camera instead of a big display screen, some might want an extra battery to increase the battery life, some might want a projector instead of a camera. The amount of customization the customers can make would be endless.

For simplicity, lets assume that there are 6 different bloks :-
1. Processor
2. Internal Memory
3. Battery
4. Display Screen
5. Camera
6. Projector

Among these bloks, the processor, internalMemory, battery and the displayScreen are mandatory as they are the minimum that a phoneblok needs to run.

Traditionally, programmers use the telescoping constructor pattern, in which you provide a constructor with only the required parameters, another with a single optional parameter, a third with two optional parameters and so on culminating in a constructor with all the optional parameters.

package com.codeskittles.learning.designpatterns.builder;

public class Phoneblok {

  private final String processor;
  private final String internalMemory;
  private final String battery;
  private final String displayScreen;
  private final String camera;
  private final String projector;

  public Phoneblok(
      final String processor,
      final String internalMemory,
      final String battery,
      final String displayScreen) {

    this(processor, internalMemory, battery, displayScreen, null);
  }

  public Phoneblok(
      final String processor,
      final String internalMemory,
      final String battery,
      final String displayScreen,
      final String camera) {

    this(processor, internalMemory, battery, displayScreen, camera, null);
  }

  public Phoneblok(
      final String processor,
      final String internalMemory,
      final String battery,
      final String displayScreen,
      final String camera,
      final String projector) {

    this.processor = processor;
    this.internalMemory = internalMemory;
    this.battery = battery;
    this.displayScreen = displayScreen;
    this.camera = camera;
    this.projector = projector;
  }
}

When you want to create a Phonebloc with just a projector and no camera, you call the constructor as below.

Phoneblok phoneBlokWithProjectorNoCamera =
        new Phoneblok(
            "Intel i9 10th gen",
            "16gb Samsung RAM",
            "4000mAh Battery",
            "UHD 4K Screen",
            null,
            "Elite Projector 4K");

Typically this constructor invocation will require many parameters that you don’t want to set, but you’re forced to pass a value. In the above scenario, we passed a value of null for camera. With “only” six parameters this may not seem so bad, but since code is always in a state of flux there is a possibility of new torch blok being added, this quickly gets out of hand as the number of parameters increases.

The telescoping constructor pattern works, but it is hard to write client code when there are many parameters, and harder still to read it. The client is left wondering what all those values mean and must carefully count parameters to find out. Long sequences of identically typed parameters can cause bugs and if the client accidentally reverses two such parameters, the compiler won’t complain, but the program will misbehave at runtime.

Phoneblok phoneBlokWithProjectorNoCamera =
        new Phoneblok(
            "16gb Samsung RAM", // Misplaced parameter. Sent internal Memory instead of Processor
            "Intel i9 10th gen",
            "4000mAh Battery",
            "UHD 4K Screen",
            null,
            "Elite Projector 4K");

// Compiler will not throw any errors, but the program will misbehave at runtime.

A second alternative when you have many optional parameters in a constructor is the JavaBeans pattern, in which you call a parameter-less constructor to create the object and then call setter methods to set each required parameter and each optional parameter.

package com.codeskittles.learning.designpatterns.builder;

public class Phoneblok {

  private String processor;
  private String internalMemory;
  private String battery;
  private String displayScreen;
  private String camera;
  private String projector;

  public Phoneblok() {}

  public void setProcessor(String processor) {
    this.processor = processor;
  }

  public void setInternalMemory(String internalMemory) {
    this.internalMemory = internalMemory;
  }

  public void setBattery(String battery) {
    this.battery = battery;
  }

  public void setDisplayScreen(String displayScreen) {
    this.displayScreen = displayScreen;
  }

  public void setCamera(String camera) {
    this.camera = camera;
  }

  public void setProjector(String projector) {
    this.projector = projector;
  }
}

This pattern has none of the disadvantages of the telescoping constructor pattern. It is easy to create instances and easy to read the code.

    Phoneblok phoneblok = new Phoneblok();

    phoneblok.setProcessor("Intel i9 10th gen");
    phoneblok.setInternalMemory("16gb Samsung RAM");
    phoneblok.setBattery("4000mAh Battery");
    phoneblok.setDisplayScreen("UHD 4K Screen");
    phoneblok.setProjector("Elite Projector 4K");

/* More readable. Client knows exactly what field is being set and also does not need to set other optional fields. */

Unfortunately, the JavaBeans pattern has serious disadvantages because construction is split across multiple calls, a JavaBean may be in an inconsistent state partway through its construction. The class does not have
the option of enforcing consistency merely by checking the validity of the constructor parameters. Attempting to use an object when it’s in an inconsistent state may cause failures that are far removed from the code containing the bug and hence difficult to debug.

Builder Pattern to the rescue which combines the safety of the telescoping constructor pattern with the readability of the JavaBeans pattern.

Builder Pattern

The Builder pattern suggests that you extract the object construction code into a different class typically named as Builder. This builder is usually a static member of the Type that it builds. To create an object you would need to perform a series of steps on the builder object.

package com.codeskittles.learning.designpatterns.builder;

// Immutable class
public class Phoneblok {

  private final String processor;
  private final String internalMemory;
  private final String battery;
  private final String displayScreen;
  private final String camera;
  private final String projector;

  private Phoneblok(final Builder builder) {
    this.processor = builder.getProcessor();
    this.internalMemory = builder.getInternalMemory();
    this.battery = builder.getBattery();
    this.displayScreen = builder.getDisplayScreen();
    this.camera = builder.getCamera();
    this.projector = builder.getProjector();
  }

  // Exposed static method to return a builder object to build objects of the Phoneblok Type.
  public static Builder getBuilder() {
    return new Builder();
  }

  private static class Builder {
    private String processor;
    private String internalMemory;
    private String battery;
    private String displayScreen;
    private String camera;
    private String projector;

    public Builder processor(final String processor) {
      this.processor = processor;
      /* Returns the builder object. By doing this the object construction becomes fluent since the steps can be chained. */
      return this;
    }

    public Builder internalMemory(final String internalMemory) {
      this.internalMemory = internalMemory;
      return this;
    }

    public Builder battery(final String battery) {
      this.battery = battery;
      return this;
    }

    public Builder displayScreen(final String displayScreen) {
      this.displayScreen = displayScreen;
      return this;
    }

    public Builder camera(final String camera) {
      this.camera = camera;
      return this;
    }

    public Builder projector(final String projector) {
      this.projector = projector;
      return this;
    }

    /* Method builds the Phoneblock object. Here is where you can add any validation if required. */
    public Phoneblok build() {
      return new Phoneblok(this);
    }

    private String getProcessor() {
      return processor;
    }

    private String getInternalMemory() {
      return internalMemory;
    }

    private String getBattery() {
      return battery;
    }

    private String getDisplayScreen() {
      return displayScreen;
    }

    private String getCamera() {
      return camera;
    }

    private String getProjector() {
      return projector;
    }
  }
}

Client code will look like the below and is easy to write and more importantly easy to read. Validity checks can be introduced in the builder’s constructor and methods to identify invalid inputs as early as possible, or can also be checked with the builder’s build method is called.

final Phoneblok bareBonesPhone =
/* Fluent API Calls */
        Phoneblok.getBuilder()
            .processor("Intel i9 10th gen")
            .internalMemory("16gb Samsung RAM")
            .battery("4000mAh Battery")
            .displayScreen("UHD 4K Screen")
            .build();
    
    final Phoneblok withProjectorAndNoCamera =
            Phoneblok.getBuilder()
                    .processor("Intel i9 10th gen")
                    .internalMemory("16gb Samsung RAM")
                    .battery("4000mAh Battery")
                    .displayScreen("UHD 4K Screen")
                    .projector("Elite Projector 4K")
                    .build();

All the code is uploaded to Github.
Co-ordinates : https://github.com/roshanvinil89/learning.git