AN OVERVIEW OF DESIGN PATTERNS IN JAVA & SINGLETON

Hansini Rupasinghe
8 min readMay 22, 2021

--

DESIGN PATTERNS

=======================================

❉ When it comes to software engineering, a design pattern is defined as a “Description of a solution to a recurring problem within a context, proven by experience to lead to a superior result when applied properly”.

❉ It can be known as a description or template that explains how to solve a problem that is applicable in various different situations.

❉ A design pattern is not something that can be directly transformed into a specific piece of code, it must be a way to document general and proven solutions that matches the realities of your program.

❉ Design patterns have catered, tested and proven;

☞ What classes to be created

☞ What methods to be implemented

☞ How to create and propagate variables

❉ Most of the developers think of design patterns as same as algorithms. But they are different from each other.

Differences between Algorithms and Design Patterns

Algorithms involve in solving computational problems, but Design patterns involve in solving design.

Algorithms always define a comprehensible set of operations that can accomplish a certain goal, while Design patterns define a more high-level explanation of a solution.

Parts of a Design Pattern

❉ People can remake the design patterns in many contexts in the way that they want them to be.

❉ There are mainly 4 sections that usually exist on design patterns.

  1. Intent

Problem and the solution will be narrated in this section.

2. Motivation

Describes the problem and the solution that the pattern makes possible in a more precise way.

3. Applicability

Defines the situations where a particular pattern is usable while depicting the context of the pattern.

4. Structure

How the classes are created and how each of them are related to each other will be described under this section.

5. Consequences

Describes the issues related to the problem, how the solution engage in resolving the problems and the benefits of using that particular solution.

6. Known Uses

Few well-known situations that have succeeded by using this solution are explained.

7. Code example

The idea behind a pattern will be much easier to understand by looking at the code example in one of the popular programming languages.

Types of Design Patterns

Types of design patterns in Java can be classified mainly into 3 categories namely;

1. Creational

⚜️ Creational patterns are involved in object creation mechanism.

⚜️ In this design pattern, objects are created while hiding the creation logic instead of using ‘new’ operator to instantiate objects directly.

⚜️ These design patterns increase the reusability and the flexibility of a given piece of code.

⚜️ There are 2 sub class creation patterns known as;

💠 Class-creation patterns

This pattern uses inheritance effectively during instantiation process.

💠 Object-creational patterns

This pattern uses delegation effectively during instantiation process.

2. Structural

⚜️ Structural patterns are involved in class and object composition that describes how to assemble objects and classes into larger structures and what classes contain and what relationships are there in between classes.

⚜️ These design patterns increase the efficiency and the flexibility of the structures.

⚜️ It uses inheritance for the process of composing interfaces.

3. Behavioral

⚜️ Behavioral patterns are involved in communication, interaction and the assignment of responsibilities among objects.

Advantages of using Design Patterns

🎀 Reusable.

🎀 Provides best solutions to various problems.

🎀 Helps to define the system architecture.

🎀 Efficient.

🎀 Speeds up the development process by providing tested and proven development paradigms.

🎀 Improves code readability.

🎀 Defines how to solve all types of problems using principles of object-oriented design.

🎀 Provides a common platform for developers.

🎀 Provides transparency to the application designs.

🎀 Provides standard terminology that can be understood by anybody.

SINGLETON

=======================================

❉ Singleton is one of the most commonly used design patters that permits only one instance of a class per container at any time.

❉ If it is Java, there is only one instance per JVM.

❉ If you implement Singleton, you should not take any arguments when you create an instance.

❉ Singleton should not be overkilled as it is very hard to carry out unit testing because there are no instance variables and no any other references to create.

❉ There are 2 forms of Singleton design pattern namely;

🔶 Lazy Instantiation — Instances are created only when required.

🔶 Early Instantiation — Instances are created at load time.

UML of Singleton Design Pattern

Ref: https://www.javatpoint.com/singleton-design-pattern-in-java

How to Implement Singleton Design Pattern?

❉ In order to implement Singleton design pattern in a piece of code, we need followings.

✔︎ Private constructor: When you make a constructor private, no one can create an instance from that. Singleton class would not be able to instantiate outside the class.

✔︎ Static member: As it is declared static, it gets memory only once. It consists of the instance of the Singleton class.

✔︎ Static factory method: It gives the global access point to the Singleton object to create the instance.

Usage of Singleton Design Pattern

  • It is used often in database and multi-threaded applications.
  • Singleton Design Pattern is used in scenarios such as caching, logging, thread pools, configuration settings, managing “service host repositories” in SOA etc.
Ref: https://images.app.goo.gl/HZ6xbUujFHXgLGwk6

Real World Example for Singleton Design Pattern

📜 There is a small scale service provider company where there is only one person for the customer care services. Customers can communicate with that person only over the phone in order to clarify their issues, to be aware of any services etc.

Only one customer can communicate with the customer care representative at one time. If the customer care representative is on a call with one customer, all the other consumers will have to wait until he ends that call. Another person will be permitted to communicate, only when a call ends.

Communication Manager Class:

➣ When a class loads itself, it eagerly creates an instance. As the constructor is private, no second instance can be created.

Main Class:

Output:

➣ When you run the above mentioned programs written in Java, you get the same instance twice. Although you assign for 2 different variables and invoke in 2 different times, it gives the same instance. This is because it is Singleton.

Even though this can be done this way, it is limiting what it can do. Therefore, this can be done in a better way as follows.

Communication Manager Class:

In the above code;

▪️ Line 3 : Do not create an instance here

▪️ Line 6 : This is a good practice because frameworks like Reflection may interfere and create a second instance using manual invoking constructor.

▪️ Line 7 : We block them if someone interfere with Reflection framework. We ask to use getCommunicationManager() instance.

▪️ Line14 and onwards: If comManager is not yet created, we create. Otherwise it will return comManager.

Output:

➣ You get the same output as in the previous implementation.

The problem with this method is that, this is not Thread-safe.

▪️ Let us assume that first thread reached Line14 in the previous code. It checks if it is null. Then it goes in and try to create and assign a value to comManager variable.

▪️ Meantime, Thread 2 comes to that particular point ( Line14) and checks if comManager is null. At this point, the instance is being creating and has not created yet. Therefore, it tells it is null. And second thread also will come in. So, it is not Thread-safe.

🔺Edge Cases : Two threads / multiple threads may create an instance.

To avoid this, we can use the principle called “DOUBLE CHECKING SINGLETON”.

Output:

➣ You get the same output as in the previous 2 implementations.

In the above code;

▪️ First thread comes to Line 14, and checks if it is null. If it is null, it goes inside and create a synchronized lock. It checks again for the second time if comManager is null. If it is null, an instance will be created.

▪️ While this instance is creating, the second thread comes. As the instance is not yet created, it says that comManager is null. Therefore, it goes to Line 15. Then it does not allow the second thread to go inside as there is one thread which is executing at the time.

▪️ Once the first thread leaves, Synchronized block allows second thread to go in and then it will check if comManager is null. As previous thread created one, second thread will not be allowed to go in. Therefore, it jumps to Line 23 and returns the same instance.

🔴 This is the correct way to implement Singleton and known as Double Checking Singleton.

Remember❗️❗️❗️

🟥 There is a mistake done by some developers. They use “Synchronized” keyword instead of “static” in method declaration. If you use it there, there is a possibility that you will get a performance hit. It would block everything when you use “Synchronized” keyword on method level. You can just block the exact code segment that you need to block rather than blocking everything.

Advantages of Singleton Design Pattern

♻️ Saves memory because only a single instance is created.

♻️ Have instance control as Singleton makes sure that all objects access the same single instance.

♻️ Maintenance is easy as it provides a single point of access to a certain instance.

♻️ Reduced namespace by avoiding global variables.

♻️ Refinement of operations is permitted through sub classing.

Disadvantages of Singleton Design Pattern

♨️ Unit Testing becomes difficult.

♨️ Single Responsibility Principle will be violated.

♨️ This design pattern can mask bad designs.

♨️ Overuse of Singleton may give problems to your application.

Important Facts to be remembered when creating a singleton class

🔔 The constructor should be declared private.

🔔 Singleton can be built using Enum in Java.

🔔 JEE 7 contains a built-in annotation named @Singleton

References

--

--