Creational Patterns

Builder

The Builder pattern can either consist of a single contructor or you can opt for a piecewise contruction like the StringBuilder/StringBuffer, the builder provids an API for constructing an object step-by-step.

Let see some examples of the Builder Pattern

StringBuilder/StringBuffer (built-in into Java)
// Small concatenation is not to bad
String hello = "hello";
System.out.println("<p>" + hello + "</p>");

// When we start getting more complex the code becomes more ugly
String[] words = {"hello", "world"};
System.out.println( "<ul><li>" + words[0] + "</li><li>" + words[1] + "</li></ul>");

// We use a Builder, we use a piecewise construction, building the string piece by piece.
// Use a StringBuilder (not synchronized) or StringBuffer (synchronized)
StringBuilder sb = new StringBuilder();
sb.append("<ul>");
for (String word : words){
    sb.append(String.format(" <li>%s</li>", word));
}
sb.append("</ul>");
System.out.println(sb);
Fluent Builder
package uk.co.datadisk.Creational.builder;

import java.util.ArrayList;
import java.util.Collections;

class HtmlElement {

    String name, text;
    ArrayList<HtmlElement> elements = new ArrayList<>();
    private final int indentSize = 2;
    private final String newLine = System.lineSeparator();

    HtmlElement() {}

    HtmlElement(String name, String text) {
        this.name = name;
        this.text = text;
    }

    // This is a recursive method
    private String toStringImpl(int indent) {
        //System.out.println("Indent: " + indent);
        StringBuilder sb = new StringBuilder();
        String i = String.join("", Collections.nCopies(indent * indentSize, " "));
        sb.append(String.format("%s<%s>%s", i, name, newLine));
        if (text != null && !text.isEmpty())
        {
            sb.append(String.join("", Collections.nCopies(indentSize*(indent+1), " ")))
                    .append(text)
                    .append(newLine);
        }

        for (HtmlElement e : elements)
            sb.append(e.toStringImpl(indent + 1));

        sb.append(String.format("%s</%s>%s", i, name, newLine));
        return sb.toString();
    }

    @Override
    public String toString() {
        return toStringImpl(0);
    }
}

class HtmlBuilder
{
    private String rootName;
    private HtmlElement root = new HtmlElement();

    public HtmlBuilder(String rootName)
    {
        this.rootName = rootName;
        root.name = rootName;
    }

    // Not Fluent
    public void addChild(String childName, String childText)
    {
        HtmlElement e = new HtmlElement(childName, childText);
        root.elements.add(e);
    }

    // Fluent - allows you to chain method calls, notice we return this and the return type is HtmlBuilder
    public HtmlBuilder addChildFluent(String childName, String childText)
    {
        HtmlElement e = new HtmlElement(childName, childText);
        root.elements.add(e);
        return this;
    }

    // delegating
    @Override
    public String toString()
    {
        return root.toString();
    }
}

public class Main_Builder_2 {

    public static void main(String[] args) {
        HtmlBuilder builder = new HtmlBuilder("ul");
        System.out.println(builder);

        System.out.println("***************************");
        builder.addChild("li", "hello");
        System.out.println(builder);

        System.out.println("***************************");
        builder.addChild("li", "world");
        System.out.println(builder);

        // Use the fluent method
        System.out.println("***************************");
        builder.addChildFluent("li", "paul").addChild("li", "valle");
        System.out.println(builder);
    }
}
Fluent Builder with Generics
package uk.co.datadisk.Creational.builder;

class Person {
    public String name, position;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", position='" + position + '\'' +
                '}';
    }
}

// We make the class Generic thus we can pass a number fo different types
// also we specify a UPPER bound of PersonBuilder<SELF>
class PersonBuilder<SELF extends PersonBuilder<SELF>> {
    protected Person person = new Person();

    public SELF withName(String name){
        person.name = name;
        // return (SELF) this;              // this is also ok and would replace the below line
        return self();
    }

    public Person build(){
        return person;
    }

    // This Generic method returns the correct type SELF
    // The reason for this is you can override this method in derived classes
    // The reason for this is you can override this method in derived classes
    protected SELF self() {
        return (SELF) this;
    }
}

// We extending the class using the PersonBuilder passing the type EmployeeBuilder
class EmployeeBuilder extends PersonBuilder<EmployeeBuilder> {
    public EmployeeBuilder worksAt(String position){
        person.position = position;
        return self();
    }

    // We can override self() to return the correct object
    @Override
    protected EmployeeBuilder self() {
        return this;
    }
}

public class Main_Builder_3 {
    public static void main(String[] args) {
        EmployeeBuilder pb = new EmployeeBuilder();
        Person paul = pb
                .withName("Paul")
                .worksAt("Developer")
                .build();
        System.out.println(paul);
    }
}
Faceted Builders (multiple Builder)
package uk.co.datadisk.Creational.builder;

// Using several builders

class Person {
    // address -  will use address builder to set these
    public String streetAddress, postcode, city;

    // employment -  will use job builder to set these
    public String companyName, position;
    public int annualIncome;

    @Override
    public String toString() {
        return "Person{" +
                "streetAddress='" + streetAddress + '\'' +
                ", postcode='" + postcode + '\'' +
                ", city='" + city + '\'' +
                ", companyName='" + companyName + '\'' +
                ", position='" + position + '\'' +
                ", annualIncome=" + annualIncome +
                '}';
    }
}

// builder facade - base case that has both builders (address and job)
class PersonBuilder {
    // The object we are building, in this case a Person Object
    Person person = new Person();

    // builders
    public PersonAddressBuilder lives() {
        return new PersonAddressBuilder(person);
    }

    public PersonJobBuilder works() {
        return new PersonJobBuilder(person);
    }

    // to retrieve the Person object
    public Person build(){
        return person;
    }
}

class PersonAddressBuilder extends PersonBuilder {
    public PersonAddressBuilder(Person person){
        this.person = person;
    }

    public PersonAddressBuilder at(String streetAddress){
        person.streetAddress = streetAddress;
        return this;                            // this makes it fluent (chaining)
    }

    public PersonAddressBuilder withPostcode(String postcode){
        person.postcode = postcode;
        return this;                            // this makes it fluent (chaining)
    }

    public PersonAddressBuilder in(String city){
        person.city = city;
        return this;                            // this makes it fluent (chaining)
    }
}

class PersonJobBuilder extends PersonBuilder
{
    public PersonJobBuilder(Person person)
    {
        this.person = person;
    }

    public PersonJobBuilder at(String companyName)
    {
        person.companyName = companyName;
        return this;                            // this makes it fluent (chaining)
    }

    public PersonJobBuilder asA(String position)
    {
        person.position = position;
        return this;                            // this makes it fluent (chaining)
    }

    public PersonJobBuilder earning(int annualIncome)
    {
        person.annualIncome = annualIncome;
        return this;                            // this makes it fluent (chaining)
    }
}

public class Main_Builder_4 {

    public static void main(String[] args) {

        PersonBuilder pb = new PersonBuilder();
        Person person = pb
                // PersonAddressBuilder
                .lives()
                  .at("123 London Road")
                  .in("London")
                  .withPostcode("SW12BC")
                // PersonJobBuilder
                .works()
                  .at("Datadisk")
                  .asA("Developer")
                  .earning(50000)
                // Person  
                .build();
        System.out.println(person);
    }
}

Factories

I will cover two types of factories, Factory Method and Abstract Factory, I will give exmaples of above, there are number of reasons to use a factory, the Object creation becomes too complex and s the constructor is not descriptive on the type of Object you want to create, you are unable to overload the same set of arguments with different names, so many constructors are created to get around this problem. One further point to make is that Factories should not have any state and thus could be ideal as a Singleton Object (see Singleton Pattern below).

Factory Method example (Inner or External)
package uk.co.datadisk.Creational.factories;

// Factory - simply create an Object and return it, but the Object may have multiple ways to build it

class Point1 {
    private double x, y;

    // NOTE: the constructor is private and will only be called by the methods below
    private Point1(double x, double y) {
        this.x = x;
        this.y = y;
    }

    // each method would replace a overloaded constructor or be able to create
    // constructors with the same arguments types.

    // NOTE: they all return a Point1 Object
    //static Point1 newCartesianPoint(double x, double y){
    //    return new Point1(x, y);
    //}

    //static Point1 newPolarPoint(double rho, double theta){
    //return new Point1( (rho *Math.cos(theta)), rho*Math.sin(theta));
    //}

    // by keeping the class inside the Point class allow us to keep the Point constructor
    // private OR break out the Factory class (see below)
    public static class Factory {

        static Point1 newCartesianPoint(double x, double y){
            return new Point1(x, y);
        }

        static Point1 newPolarPoint(double rho, double theta){
            return new Point1( (rho *Math.cos(theta)), rho*Math.sin(theta));
        }
    }

    @Override
    public String toString() {
        return "Point1{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

// break out the Factory class but you would have to make the Point constructor public
// thus you have two ways to create a Point object

//public static class Factory {
//
//    static Point1 newCartesianPoint(double x, double y){
//        return new Point1(x, y);
//    }
//
//    static Point1 newPolarPoint(double rho, double theta){
//        return new Point1( (rho *Math.cos(theta)), rho*Math.sin(theta));
//    }
//}

public class Main_Factories_1 {

    public static void main(String[] args) {
        Point1 cartesianPoint = Point1.Factory.newCartesianPoint(3,4);
        Point1 polarPoint = Point1.Factory.newPolarPoint(3,4);

        System.out.println("Cartesian: " + cartesianPoint);
        System.out.println("Polar: " + polarPoint);
    }
}
Abtract Factory example
package uk.co.datadisk.Creational.factories;

interface Computer {
    int getRam();
    String getCPU();
    int getHD();
}

class Laptop implements Computer {

    private int ram;
    private String cpu;
    private int hd;

    public Laptop(int ram, String cpu, int hd) {
        this.ram = ram;
        this.cpu = cpu;
        this.hd = hd;
    }

    @Override
    public int getRam() {
        return this.ram;
    }

    @Override
    public String getCPU() {
        return this.cpu;
    }

    @Override
    public int getHD() {
        return this.hd;
    }
}

class Desktop implements Computer {

    private int ram;
    private String cpu;
    private int hd;

    public Desktop(int ram, String cpu, int hd) {
        this.ram = ram;
        this.cpu = cpu;
        this.hd = hd;
    }

    @Override
    public int getRam() {
        return this.ram;
    }

    @Override
    public String getCPU() {
        return this.cpu;
    }

    @Override
    public int getHD() {
        return this.hd;
    }
}

class ComputerFactory {
    public Computer getComputer(String type, int ram, String cpu, int hd) {

        // Return a Computer specialized object (laptop or desktop).
        switch (type){
            case "Laptop":
                return new Laptop(ram, cpu, hd);
            case "Desktop":
                return new Desktop(ram, cpu, hd);
        }
        return null;
    }
}

public class Main_Factories_3 {

    public static void main(String[] args) {
        ComputerFactory cf = new ComputerFactory();
        Computer laptop = cf.getComputer("Laptop", 8, "Intel i5", 1);
        displayComputer(laptop, "Laptop");

        Computer desktop = cf.getComputer("Desktop", 16, "Intel i7", 2);
        displayComputer(desktop, "Desktop");
    }

    public static <T> void displayComputer(T computer, String type) {
        Computer comp = (Computer) computer;
        System.out.println(type + ": Memory " + comp.getRam() + "GB, CPU " + comp.getCPU() + ", HD " + comp.getHD() + "TB");
    }
}

Prototype

The Prototype pattern again is for creating Objects, sometimes it's easier to copy and Object than to create one, and thats what the Prototype pattern is about copying objects and then customizing it, sometimes this is referred to as cloning, however one point to make is that a deep copy is performed which means all objects references (recursively) inside the object to be copied are also copied.

Using Cloneable example (Not recommended)
package uk.co.datadisk.Creational.prototype;

// Prototype = A partially or fully initialized object that you copy (clone)
// and make use of

import java.util.Arrays;

class Address implements Cloneable {
    public String streetName;
    public int houseNumber;

    public Address(String streetName, int houseNumber) {
        this.streetName = streetName;
        this.houseNumber = houseNumber;
    }

    @Override
    public String toString() {
        return "Address{" +
                "streetName='" + streetName + '\'' +
                ", houseNumber=" + houseNumber +
                '}';
    }

    // deep copy
    @Override
    public Object clone() throws CloneNotSupportedException {
        return new Address(streetName, houseNumber);
    }
}

class Person implements Cloneable {
    public String[] names;
    public Address address;

    public Person(String[] names, Address address) {
        this.names = names;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "names=" + Arrays.toString(names) +
                ", address=" + address +
                '}';
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return new Person(names.clone(), (Address) address.clone());
    }
}

public class Main_Prototype_1 {

    public static void main(String[] args) throws Exception {

        // Only one Person object is created
        Person paul = new Person(new String[]{"Paul", "Valle"}, new Address("London Road", 123));

        // YOU CANNOT DO THE BELOW TO COPY AN OBJECT
        // lorraine = paul;                             // make some changes

        // need cast as Object is returned
        Person lorraine = (Person) paul.clone();
        lorraine.names[0] = "Lorraine";
        lorraine.address.houseNumber = 124;

        System.out.println(paul);
        System.out.println(lorraine);
    }
}
Copy Constructor example (better than Cloneable)
package uk.co.datadisk.Creational.prototype;

// Copy constructor, better than using Cloneable

class Address2 {
   public String streetAddress, city, country;

    public Address2(String streetAddress, String city, String country) {
        this.streetAddress = streetAddress;
        this.city = city;
        this.country = country;
    }

    @Override
    public String toString() {
        return "Address2{" +
                "streetAddress='" + streetAddress + '\'' +
                ", city='" + city + '\'' +
                ", country='" + country + '\'' +
                '}';
    }

    // draw back is that you need copy constructors and depending on number of variables
    // this could get out of hand
    public Address2(Address2 other){
       this(other.streetAddress, other.city, other.country);
    }
}

class Employee  {
    public String name;
    public Address2 address2;

    public Employee(String name, Address2 address2) {
        this.name = name;
        this.address2 = address2;
    }

    public Employee(Employee other){
        name = other.name;
        address2 = new Address2(other.address2);
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", address2=" + address2 +
                '}';
    }
}

public class Main_Prototype_2 {

    public static void main(String[] args) {

        Employee paul = new Employee("Paul", new Address2("123 London Road", "London", "UK"));

        Employee lorraine = new Employee(paul);

        lorraine.name = "Lorraine";
        lorraine.address2.streetAddress = "124 London Road";

        System.out.println(paul);
        System.out.println(lorraine);

    }
}
Copy Through Serialization (best option)
package uk.co.datadisk.Creational.prototype;

// Perform deep copy using serialization (you can also use reflection as well)

import org.apache.commons.lang3.SerializationUtils;

import java.io.Serializable;

class Foo implements Serializable {
    public int stuff;
    public String whatever;

    public Foo(int stuff, String whatever) {
        this.stuff = stuff;
        this.whatever = whatever;
    }

    @Override
    public String toString() {
        return "Foo{" +
                "stuff=" + stuff +
                ", whatever='" + whatever + '\'' +
                '}';
    }
}

public class Main_Prototype_3 {

    public static void main(String[] args) {
        Foo foo = new Foo(42, "life");

        // deep copy
        Foo foo2 = (Foo) SerializationUtils.clone(foo);   // used to be called roundtrip()

        foo2.whatever = "xyz";
        foo2.stuff = 50;

        System.out.println(foo);
        System.out.println(foo2);
    }
}

Singleton

The Singleton Pattern basically means that you have one and only one Object in the system, and all other Objects/code will access this one Object, you code it so that you can one create one instance of the Object, hence the term Singleton.

Lots of developers see a Singleton as a design smell, others are happy to use them and some the reasons are below:

There are many of ways to create singletons, I will cover 6 different ways, there is no best one but as each offers something different:

Basic Singleton (can be used in most cases)
package uk.co.datadisk.Creational.singleton;

// Singleton means only one instance of an Object

class BasicSingleton {

    private static final BasicSingleton INSTANCE = new BasicSingleton();
    private int value = 0;

    // Must make the constructor private
    private BasicSingleton(){ }

    // allow access to the singleton
    public static BasicSingleton getInstance(){
        return INSTANCE;
    }

    // Getter and Setter
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
}

public class Main_Singleton_1 {

    public static void main(String[] args) {

        BasicSingleton singleton = BasicSingleton.getInstance();
        singleton.setValue(123);
        System.out.println(singleton.getValue());
    }
}
Problems with Basic Singleton
package uk.co.datadisk.Creational.singleton;

// Singleton means only one instance of an Object

import java.io.*;

class BasicSingleton2 implements Serializable {

    private static final BasicSingleton2 INSTANCE = new BasicSingleton2();
    private int value = 0;

    // Must make the constructor private
    private BasicSingleton2(){ }

    // allow access to the singleton
    public static BasicSingleton2 getInstance(){
        return INSTANCE;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    // Used to protect against using serialization to get around a singleton
    // If a serializable object has a readResolve method it will be called
    protected Object readResolve() {
        return INSTANCE;
    }
}

public class Main_Singleton_2 {

    public static void main(String[] args) throws Exception {

        // Problems
        // 1. You can use reflection to call it and make it public
        // 2. Use serialization, which can get private members (see the fix above the readResolve() method)

        BasicSingleton2 singleton = BasicSingleton2.getInstance();
        singleton.setValue(111);

        String filename = "src\\uk\\co\\datadisk\\singleton\\singleton.bin";
        saveToFile(singleton, filename);

        singleton.setValue(222);
        BasicSingleton2 singleton2 = readFromFile(filename);

        System.out.println(singleton == singleton2);
        System.out.println(singleton.getValue());
        System.out.println(singleton2.getValue());
    }

    static void saveToFile(BasicSingleton2 singleton, String filename) throws Exception {
        try(FileOutputStream fileOut = new FileOutputStream(filename);
            ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            out.writeObject(singleton);
        }
    }

    static BasicSingleton2 readFromFile(String filename) throws Exception {
        try (FileInputStream fileIn = new FileInputStream(filename);
             ObjectInputStream in = new ObjectInputStream(fileIn)){
           return (BasicSingleton2) in.readObject();
        }
    }
}
Static Block Singleton
package uk.co.datadisk.Creational.singleton;

class StaticBlockSingleton {

    public static StaticBlockSingleton instance;

    private StaticBlockSingleton() {
        System.out.println("Singleton is initializing");
    }

    // Use a static block to create the singleton
    static {
        try {
            instance = new StaticBlockSingleton();
        } catch (Exception e){
            System.err.println("failed to create singleton");
        }
    }

    public static StaticBlockSingleton getInstance(){
        return instance;
    }
}

public class Main_Singleton_3 {

    public static void main(String[] args) {
        StaticBlockSingleton singleton = StaticBlockSingleton.getInstance();
    }

}
Lazy Singleton (with synchronization)
package uk.co.datadisk.Creational.singleton;

// Lazy and Thread safe but not the best solution, Main_Singleton_5

class LazySingleton {

    // NOTICE WE DON'T INITIALIZE THE SINGLETON YET
    private static LazySingleton instance;

    public LazySingleton() {
        System.out.println("Initializing a lazy singleton");
    }

    // Below would work but you are synchronizing too much and thus impacts
    // performance
//    public static synchronized LazySingleton getInstance(){
//        if (instance == null){
//            instance = new LazySingleton();
//        }
//        return instance;
//    }

    // THIS IS WERE WE INITILAIZE THE SINGLETON
    // double-check locking (now out dated but still in the wild)
    public static LazySingleton getInstance(){
        if(instance == null){                           // first check
            synchronized (LazySingleton.class){
                if (instance == null){                  // second check (double-check)
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}
Inner Static Singleton
package uk.co.datadisk.Creational.singleton;

// Lazy and Thread safe and does not use synchronization

class InnerStaticSingleton {
    private InnerStaticSingleton(){}

    // the INSTANCE is a static final
    private static class Impl{
        private static final InnerStaticSingleton INSTANCE =
                new InnerStaticSingleton();
    }

    public static InnerStaticSingleton getInstance(){
        return Impl.INSTANCE;
    }
}

public class Main_Singleton_5 {
    public static void main(String[] args) {
        InnerStaticSingleton singleton = InnerStaticSingleton.getInstance();
    }
}
Enum Based Singleton
package uk.co.datadisk.Creational.singleton;

// enums are automatically serializable

// NOTE: two problem using enums for singletons
//       1. You cannot serialize enum singletons (only the name is serialized)
//       2. You cannot inherit from Enum (period)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

enum EnumBasedSingleton {
    INSTANCE;               // this will only be serialized (must be single member)

    // the constructor is always private by default
    EnumBasedSingleton(){
        value = 42;
    }

    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

public class Main_Singleton_6 {

    static void saveToFile(EnumBasedSingleton singleton, String filename)
            throws Exception
    {
        try (FileOutputStream fileOut = new FileOutputStream(filename);
             ObjectOutputStream out = new ObjectOutputStream(fileOut))
        {
            out.writeObject(singleton);
        }
    }

    static EnumBasedSingleton readFromFile(String filename)
            throws Exception
    {
        try (FileInputStream fileIn = new FileInputStream(filename);
             ObjectInputStream in = new ObjectInputStream(fileIn) )
        {
            return (EnumBasedSingleton)in.readObject();
        }
    }

    //
    public static void main(String[] args) throws Exception {
        String filename = "src\\uk\\co\\datadisk\\singleton\\myfile.bin";

        // run again with next 3 lines commented out

//        EnumBasedSingleton singleton = EnumBasedSingleton.INSTANCE;
//        singleton.setValue(111);
//        saveToFile(singleton, filename);

        EnumBasedSingleton singleton2 = readFromFile(filename);
        System.out.println(singleton2.getValue());
    }
}
MonoState Singleton
package uk.co.datadisk.Creational.singleton;

// Using MonoState to create a singleton

class ChiefExecutiveOfficer {

    // make member variables static
    private static String name;
    private static int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        ChiefExecutiveOfficer.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        ChiefExecutiveOfficer.age = age;
    }

    @Override
    public String toString() {
        return "ChiefExecutiveOfficer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Main_Singleton_7 {

    public static void main(String[] args) {
        ChiefExecutiveOfficer ceo1 = new ChiefExecutiveOfficer();
        ceo1.setName("Paul Valle");
        ceo1.setAge(50);

        ChiefExecutiveOfficer ceo2 = new ChiefExecutiveOfficer();
        ceo2.setName("Lorraine Valle");
        ceo2.setAge(50);

        ChiefExecutiveOfficer ceo3 = new ChiefExecutiveOfficer();

        // Both will be the same
        System.out.println(ceo1);
        System.out.println(ceo2);
        System.out.println(ceo3);           // this points to the same static members (or singleton)
    }
}