Design Patterns in JAVA

Design Patterns in JAVA Design pattern is defined as the re-usable form of a solution to a design problem. With design pattern you can document a solution to a design problem. Design pattern was introduced by the architect Christopher Alexander and has been adapted for various other disciplines. Design patterns are very popular amongst the developer.

Design pattern is defined as the re-usable form of a solution to a design problem. With design pattern you can document a solution to a design problem. Design pattern was introduced by the architect Christopher Alexander and has been adapted for various other disciplines. Design patterns are very popular amongst the developers as they provide solutions to general problems that software developers face. It provides a template to solve common problems while designing a system or an application.

Design patterns act as a common language between developers so that each developer easily understands the concept while working with common problems.

Design patterns have evolved after many trials and captured solutions that have been applied to problems successfully. Even a new developer can learn a lot from these design patterns.

Benefits of using Design Patterns in JAVA

  1. Design patterns have evolved after successfully been applied to problems. Today design patterns are already defined and provides standard approach to solve common problems. It saves a lot of developer’s time if they use these patterns sensibly.
  2. With design patterns developers can develop more robust and maintainable code. It also promotes reusability and helps in reducing total development cost of the application.
  3. Design patterns are already tested and successfully applied in many common recurring problems therefore applying these patterns will help in making code easy to understand, debug and faster development.

In context of JAVA Design Patterns are divided into three categories – creational, structural and behavioral patterns.

Creational Design Patterns

With creational design pattern you can instantiate an object in the best possible manner for specific problems. The object creation process can lead to unwanted complexity in the design problems. This is where creational design patterns provide solution by controlling the object creation process in different ways. There are five different creational design patterns:

  1. Singleton Pattern
  2. Factory Pattern
  3. Abstract Factory Pattern
  4. Builder Pattern
  5. Prototype Pattern

For the sake of this article we’ll be covering Singleton Pattern. Singleton pattern make sure that only one instance of class exists by restricting instantiation of a class. It is one of the Gangs of Four Design Patterns. It is one of the simplest design patterns in JAVA. Although it is simplest design pattern, but it has a lot of implementation concerns.

Learn Advanced Java

Let’s learn about Singleton Design pattern principles, its usage best practices and different ways to implement.

  1. Singleton Eager Initialization

In Eager Initialization the instance of a class is created at the time of class loading.

public class SingletonEager {

private static volatile SingletonEager instance = new SingletonEager ();

 

// private constructor

private SingletonEager() {

}

 

public static SingletonEager getInstance() {

return instance;

}

}

The instance is created irrespective of the fact whether the instance is required in runtime or not in the client application. To solve this issue, you can leave the instance unused if it’s not a big object.

  1. Static Block Initialization

Static blocks are executed during class loading before constructor is called. It is similar to Eager Initialization except for the fact that class is created in static block which provides an option for exception handling.

public class SingletonStaticBlock {

private static final SingletonStaticBlock INSTANCE;

 

static {

try {

INSTANCE = new SingletonStaticBlock ();

} catch (Exception e) {

throw new RuntimeException(“It wasn’t the way expected!”, e);

}

}

 

public static SingletonStaticBlock getInstance() {

return INSTANCE;

}

 

private SingletonStaticBlock() {

// …

}

}

The drawback of this type of initialization is that if only 2 or 3 static fields are required out of few static fields we need to create an instance irrespective of whether it is required or not.

3.Lazy Initialization

Lazy Initialization creates instance in the global access method. By lazy initialization you can actually delay the creation of an object until it is required.

public final class SingletonLazy {

private static volatile SingletonLazy instance = null;

// private constructor

private SingletonLazy() {

}
public static SingletonLazy getInstance() {

if (instance == null) {

synchronized (SingletonLazy.class) {

instance = new SingletonLazy();

}

}

return instance;

}

}

With this method you can check if the instance is already created using instance variable. It will create an instance if the instance is null else it will return the reference if the instance is already created.
If there are two threads, both will create the instance and check if the instance is null. Now if both the threads identify a null instance then they’ll create an instance by sequentially going into a synchronized block. This will result in two instances at the end. To resolve the issue, you can use double-checked locking method. It will recheck the instance variable in a synchronized block.

public class SingletonLazy {

private static volatile SingletonLazy instance = null;

// private constructor

private SingletonLazy() {

}
public static SingletonLazy getInstance() {

if (instance == null) {

synchronized (SingletonLazy.class) {

// Double check

if (instance == null) {

instance = new SingletonLazy();

}

}

}

return instance;

}

}

4.Bill Pugh Singleton

Bill Pugh devised an approach to create Singleton class using inner static helper class. Due to issues with Java memory model if there are multiple threads then each thread will create instance simultaneously. This is where Bill Pugh Singleton method works. 

public class SingletonByBillPugh {

private SingletonByBillPugh() {

}
private static class LazyHolder {

private static final SingletonByBillPugh INSTANCE = new

SingletonByBillPugh();

}
public static SingletonByBillPugh getInstance() {

return LazyHolder.INSTANCE;

}

}

5.Singleton using Enum

This Singleton pattern was suggested by Joshua Bloch to use Enum as its value is instantiated only once in Java. With Enum only one instance is guaranteed. It provides implicit support for thread safety and is a good way to have singleton with minimal effort. 

public enum SingletonEnum {

INSTANCE;

public void someMethod(String param) {

// some class member

}

}

6.Singleton Object with readResolve()

If the application is distributed, objects are serialized frequently into the file system so that they can be read later when required. While de-serializing the objects always creates a new instance. 

public class SingletonDemo implements Serializable {

private volatile static SingletonDemo instanceOfSingleton = null;

public static SingletonDemo getInstance() {

if (instanceOfSingleton == null) {

instanceOfSingleton = new SingletonDemo();

}

return instanceOfSingleton;

}
private int i = 10;
public int getI() {

return i;

}
public void setI(int i) {

this.i = i;

}

}

We’ll serialize this class and again de-serialize it after some changes:

public class SerializableTest {

static SingletonDemo firstInstance = SingletonDemo.getInstance();

public static void main(String[] args)   {

try {

// Serialize to a file

ObjectOutput out = new ObjectOutputStream(new FileOutputStream(“filename.ser”));

out.writeObject(firstInstance);

out.close();

firstInstance.setI(20);

// Serialize to a file

ObjectInput in = new ObjectInputStream(new FileInputStream(“filename.ser”));

SingletonDemo secondInstance = (SingletonDemo) in.readObject();

in.close();

System.out.println(firstInstance.getI());

System.out.println(secondInstance.getI());

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}
Output:

20

10

Since both variables have different values, there will be two instances in the class which will create the same problem of multiple instances in the application. To resolve the issue we’ll include readResolve() method in our class. The readResolve() method is invoked when the object is de-serialized. The existing instance must be returned inside this method to ensure a single instance.

public class SingletonDemo implements Serializable {

private volatile static SingletonDemo instance = null;

public static SingletonDemo getInstance() {

if (instance == null) {

instance = new SingletonDemo();

}

return instance;

}
protected Object readResolve() {

return instance;

}
private int i = 10;

public int getI() {

return i;

}
public void setI(int i) {

this.i = i;

}

}
Output:

20

20

7.Singleton Object with serialVersionUId

Serial version id is required when class structure changes between serialization and de-serialization. Java Virtual Machine will give an exception in de-serializing process when there is a changed class structure.

java.io.InvalidClassException: singleton.SingletonDemo; local class incompatible: stream classdesc serialVersionUID = 5026910492258526905, local class serialVersionUID =3597984220566440782

at java.io.ObjectStreamClass.initNonProxy(Unknown Source)

at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)

at java.io.ObjectInputStream.readClassDesc(Unknown Source)

at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)

at java.io.ObjectInputStream.readObject0(Unknown Source)

at java.io.ObjectInputStream.readObject(Unknown Source)

at singleton.SerializationTest.main(SerializableTest.java:24)

Only by adding a serial version id to the class this issue can be resolved. The compiler will be prevented from throwing the exception, instead it will load the available instance variables only.Now you must have got the idea how to implement singleton design pattern in your application. You can follow the below mentioned code to ensure that only one instance of a class is there in the whole application.

public class SingletonDemo implements Serializable {

private static final long serialVersionUID = 1L;

private SingletonDemo() {

// private constructor

}
private static class SingletonDemoHolder {

public static final SingletonDemo INSTANCE = new SingletonDemo();

}
public static SingletonDemo getInstance() {

return SingletonDemoHolder.INSTANCE;

}
protected Object readResolve() {

return getInstance();

}

}

I hope this article helps you to understand fine details of Singleton design pattern and Singleton best practices.

Leave a reply:

Your email address will not be published.

Site Footer

Not found