Creational Design Patterns

Singleton Pattern

@ Intent:

A creational design pattern that ensures that a class has only one instance, while providing a global access point to this instance.

:( Problem:

The Singleton pattern solves 2 problems at the same time thus violating the Single Responsibility Principle:

1. Ensure that a class has just a single instance.

2. Provide a global access point to that instance.

:) Solution

All implementations of the Singleton have these two steps in common:

If code has access to the Singleton class, then it’s able to call the Singleton’s static method. So whenever that method is called, the same object is always returned.

® Real-World Analogy

The government is an excellent example of the Singleton pattern. A country can have only one official government.

Regardless of the personal identities of the individuals who form governments, the title, “The Government of X”, is a global point of access that identifies the group of people in charge.

∆ Structure

Class can’t have a public constructor, so the only way to get its object is to call the getInstance method. This method caches the first created object and returns it in all subsequent calls.

Ω Applicability

Use the Singleton pattern when a class in the program should have just a single instance available to all clients; for example, a single database object shared by different parts of the program.

The Singleton pattern disables all other means of creating objects of a class except for the special creation method. This method either creates a new object or returns an existing one if it has already been created.

Use the Singleton pattern when you need stricter control over global variables.

Unlike global variables, the Singleton pattern guarantees that there’s just one instance of a class. Nothing, except for the Singleton class itself, can replace the cached instance.

Note:- We can always adjust this limitation and allow creating any number of Singleton instances. The only piece of code that needs changing is the body of the getInstance method.

[√] How to Implement
  1. Add a private static field to the class for storing the singleton instance.
  2. Declare a public static creation method for getting the singleton instance.
  3. Implement lazy initialization inside the static method. It should create a new object on its first call and put it into the static field. The method should always return that instance on all subsequent calls.
  4. Make constructor of the class private. The static method of the class will still be able to call the constructor, but not the other objects.
  5. Go over the client code and replace all direct calls to the singleton’s constructor with calls to its static creation method.
∑ Pros and Cons

Pros:

Cons:

£ Relations with Other Patterns
</> Java Code Example
Naive Singleton (single-threaded)

It’s pretty easy to implement a sloppy Singleton. Just need to hide the constructor and implement a static creation method.

Singleton.java : Singleton

public final class Singleton {
    private static Singleton instance;
    public String value;

    private Singleton(String value) {
        // The following code emulates slow initialization.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        this.value = value;
    }

    public static Singleton getInstance(String value) {
        if (instance == null) {
            instance = new Singleton(value);
        }
        return instance;
    }
}

DemoSingleThread.java: Client code

public class DemoSingleThread {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance("FOO");
        Singleton anotherSingleton = Singleton.getInstance("BAR");
        System.out.println(singleton.value);
        System.out.println(anotherSingleton.value);
    }
}

Output:

FOO
FOO
Naïve Singleton (Multi-Threaded)

The same class behaves incorrectly in a multithreaded environment.

Multiple threads can call the creation method simultaneously and get several instances of Singleton class.

Singleton.java: Singleton

public final class Singleton {
    private static Singleton instance;
    public String value;

    private Singleton(String value) {
        // The following code emulates slow initialization.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        this.value = value;
    }

    public static Singleton getInstance(String value) {
        if (instance == null) {
            instance = new Singleton(value);
        }
        return instance;
    }
}

DemoMultiThread.java: Client code

public class DemoMultiThread {
    public static void main(String[] args) {
        Thread threadFoo = new Thread(new ThreadFoo());
        Thread threadBar = new Thread(new ThreadBar());
        threadFoo.start();
        threadBar.start();
    }

    static class ThreadFoo implements Runnable {
        @Override
        public void run() {
            Singleton singleton = Singleton.getInstance("FOO");
            System.out.println(singleton.value);
        }
    }

    static class ThreadBar implements Runnable {
        @Override
        public void run() {
            Singleton singleton = Singleton.getInstance("BAR");
            System.out.println(singleton.value);
        }
    }
}

Output:

FOO
BAR
Thread-safe Singleton with lazy loading

To fix the problem, we have to synchronize threads during first creation of the Singleton object.

public final class Singleton {
    // The field must be declared volatile so that double check lock would work correctly.
    private static volatile Singleton instance;

    public String value;

    private Singleton(String value) {
        this.value = value;
    }

    public static Singleton getInstance(String value) {
        // The approach taken here is called double-checked locking (DCL). It exists to prevent race 
        // condition between multiple threads that may attempt to get singleton instance at the same time,
        // creating separate instances as a result.
        //
        // It may seem that having the `result` variable here is completely pointless. 
        // There is, however, a very important caveat when implementing double-checked locking in Java,
        // which is solved by introducing this local variable.
        Singleton result = instance;
        if (result != null) {
            return result;
        }
        synchronized(Singleton.class) {
            if (instance == null) {
                instance = new Singleton(value);
            }
            return instance;
        }
    }
}


Singleton Design Pattern

public class LazyInitializedSingleton {
    private static LazyInitializedSingleton instance;
    private LazyInitializedSingleton(){}
    
    public static LazyInitializedSingleton getInstance(){
        if(instance == null){
            instance = new LazyInitializedSingleton();
        }
        return instance;
    }
}

Factory Design Pattern

OS.java

Screenshot 2020-12-12 at 10.14.39 AM

Android.java

Screenshot 2020-12-12 at 10.14.10 AM

IOS.java

Screenshot 2020-12-12 at 10.13.36 AM

Android.java

Screenshot 2020-12-12 at 10.12.20 AM

Windows.java

Screenshot 2020-12-12 at 10.11.27 AM

OperatingSystemFactory.java

Screenshot 2020-12-12 at 10.09.26 AM

FactoryMain.java

Screenshot 2020-12-12 at 10.10.25 AM