Software Design Patterns

Anne Susmitha Gunasekaran
16 min readJul 19, 2022

--

We will talk about Java design patterns in this article. In Java, design patterns are solutions or guidelines to specific problems programmers generally face during software development that are based on a set of rules and requirements. Each pattern is like a blueprint that we can customize to solve a particular design problem in our code.

There are several design patterns and their subcategories. According to the Gang of Four’s book, Java designed patterns are categorized under three categories. such as creational design patterns, structural design patterns, and behavioral design patterns. Under these categories, they put 23 design patterns that we can follow to pattern our coding.

We can see them in the picture shown below.

Figure 01 : Types of Design patterns in Java

⭐️Singleton Design Pattern

We will mainly focus on the singleton pattern in this article. You know the singleton pattern comes under the creational design pattern type by looking at the above shown picture. Aside from the singleton pattern, there are four others: the factory pattern, the abstract factory pattern, the builder pattern, and the prototype pattern. Creational design pattern is all about class instantiation in these process models. This design may be further subdivided between techniques for creating classes and methods for creating objects.

Singleton pattern is one of the most commonly used design patterns. Singleton means one instance per container of the class in the JVM. A singleton class is that class that will prevent initialization of only a single instance. That is, no matter how many times it is called by any number of places from anywhere in the application, it will return the same instance that was created initially by the class itself.

The singleton class must give a global access point to the class instance. For logging, object driving, caching, and thread pooling, the Singleton design is employed. Other design patterns, such as Abstract Factory, Builder, Prototype, and Facade, also use the singleton design pattern.

When to Use Singleton Design Pattern

  • It’s good practice to keep all loggers as Singletons which increases performance.
  • Classes which provide access to configuration settings for the application.
  • Classes that contain resources that are accessed in shared mode.
  • For resources that are expensive to create like database connection objects.

What is the design pattern of a singleton?

The design pattern of a singleton is so basic that we need to hide the constructor of the class. So that the application cannot initialize that class because of the constructor is hidden.

Secondly, we will need to provide a global access to that instance of the class which was created by the class itself and it will return the only and solved instance of that class.

How it helps?

This design pattern will solve problems like:

A class will have only one instance. This instance can be easily accessible by any part of the application and the class can itself control its instantiation.

Singleton class implementation

Typically this is done by the following steps:

  1. Declare all the constructions of the class to be private.
  2. Provide a static method that will return the reference to the instance that was created by the class itself.

Initialization

There are two types of initialization in the Singleton design pattern.

  1. Early Initialization: Once the class has loaded, the instance is generated in early initialization.

We can see early initialization in detail using the following example:

Figure 02: Example for early initialization

In this above example, we have a class called singleton and then we define a public static final singleton instance to be equal to the new singleton instance. Firstly, we have made its constructor private as required by a singleton class, and secondly, we have provided a public static method that is called get instance, which returns this instance that was created initially by the class when it was loaded into the memory. As we can see, this way of creating a singleton, that is by early loading, is straight safe, but it is not as efficient as compared to lazy initialization.

2. Lazy Initialization: It is only created in lazy loading when the method for creating the instance is initially called.

We can see lazy initialization in detail using the following example:

Figure 03: Example for lazy initialization in single thread

This method is appropriate for single threaded applications and not for multi threaded. because if two or more threads are concurrently getting instance of this class that is concurrently accessing this get instance method. Risk conditions will occur and both of the threads will see that the instance was not initialized so it is not thread safe.

Figure 04: Example for lazy initialization in multi thread

Suppose we have two threads, A and B, both will come here and they will see that the instance will be equal to null, so they both will come to this line that is a synchronized singleton of that class, so one of the threads will only get a chance to enter this synchronized block. If thread A enters the synchronized block and thread B is kept waiting here, then thread B will directly come out of this block and it will have the instance that was created by thread A. This type of double checking is called double check locking mechanism in Java.

Figure 05: Example for double checked locking in java

Other than these, we can create singleton patterns using the enum.

Figure 06: Example for singleton using enum

Advantages of Singleton Design pattern

  • It provides a single point if access to a particular instance, so it is easy to maintain.
  • It can be implemented interfaces.
  • It can be initialized using lazy initialization.
  • It has Static Initialization.
  • It help to It hide dependencies.
  • It can be also inherit from other classes.

Disadvantages of Singleton Design pattern

  • Unit testing is more difficult, because it introduces a global state into an application.
  • This pattern reduces the potential for parallelism within a program, because to access the singleton in a multi-threaded system, an object must be serialized by locking.

Next we will move to the next design pattern.

⭐️Factory Design Pattern

Factory pattern comes under the creational design patterns. It provides an interface or abstract class for creating an object and allows its subclasses to decide which class to be instantiated. According to “Gang of Four”, this pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. This pattern is used when we have a superclass with multiple sub-classes and based on input, we need to return one of the sub-class.

This pattern delegates the responsibility of initializing a class from the client to a particular factory class by creating a type of virtual constructor. To achieve this, we rely on a factory which provides us with the objects, hiding the actual implementation details. The created objects are accessed using a common interface.

When to use Factory Design Pattern

  • When the parent classes choose the creation of objects to its sub-classes.
  • When a class doesn’t know which sub-class should create the instance.
  • When a class wants that its sub-classes should specify the objects to be created.
  • when you want to offer your library’s users the ability to extend its internal components

Factory pattern Implementation

I will explain this pattern using Library storage example.

First we need to create a Library interface and concrete classes implementing the interface.

Next we want to create a LibraryFactory class.

Then we want to create Reader class, to use LibraryFactory to get a Library object.

Finally it will pass information of NewsPaper, StoryBook, ScienceBook and ReligionBook to LibraryFactory to get the type of object it needs.

Figure: Implementation of NewsPaper.java class
Figure: Implementation of StoryBook.java class

Output

Advantages of Factory Design pattern

  • Factory Method Pattern allows the sub-classes to choose the type of objects to create.
  • Modular expandability of the application.
  • Good testability.
  • The implementation only interacts with parent abstract class or interface. Therefore, it can work with any classes that implement that interface or that extends that abstract class
  • Significant method names.

Disadvantages of Factory Design pattern

  • High number of required classes.
  • Extension of the application is very elaborate

Abstract Factory Pattern

In the factory design section, we saw how the Factory Method design pattern could be used to create objects related to a single family. But the Abstract Factory Design Pattern is used to create families of related or dependent objects. It’s also sometimes called a factory of factories.

Next we will move to the next design pattern.

⭐️Prototype Design Pattern

This is one of the creational design patterns types. This is not quite a popular pattern, but this is a really useful design pattern. When you need to create an instance of an object each time. So that could be quite expensive. So what this encourages is you create the first instance and you register, and the next time you just clone from the original instance, you don’t create a new instance.

When generating new objects, this pattern does not use the new keyword. Whether the user requires a shallow copy or a deep copy, the architecture must be carefully chosen. Deep copying refers to the process of copying each and every object and value to a new object from the inside out. Shallow copying just duplicates the object’s top level if there are references to an older object. The original object may be impacted if the user obtained the shallow copy, copied references from the original object, and changed them in the new object. This pattern is created with a helper class. It referred to as registry.

When to use Prototype Design Pattern

  • When the classes are instantiated at runtime.
  • When the cost of creating an object is expensive or complicated.
  • When you want to keep the number of classes in an application minimum.
  • When the client application needs to be unaware of object creation and representation.

Prototype pattern Implementation

We can take the ColorStore example to store existing objects to explain the prototype design pattern.

First we need to create Color class which contains clone () method to create an object from existing objects.

Then we want to create blackColor and blueColor child classes of Color parent class.

Next we need to create ColorStore class.

Finally we want to create Prototype driver class.

Output

Advantages of Prototype Design pattern

  • Prototype model is that it allows for active involvement in testing its effectiveness.
  • It allows you to detect any missing functionality during testing phase before mass production begins.
  • It can provide quick feedback on your product.
  • It can help to increase customer satisfaction with your product.
  • It allows you to make changes to your product quickly.

Disadvantages of Prototype Design pattern

  • The process of a prototype model is time-consuming as it requires a lot of effort to be put in by different departments.
  • it creates a misconception in people’s minds regarding the arrival of the final product.

Next we will move to the next design pattern.

⭐️Builder Design Pattern

Builder design pattern is one of the patterns of creational design patterns. According to “Gang of Four”, this pattern allows for the step-by-step creation of complex objects using the correct sequence of actions. The construction is controlled by a director object that only needs to know the type of object it is to create.

In some cases, we must use multiple constructors in our program. If you do this in the constructors, your code will become extremely complicated. because you need to implement multiple constructors. Some people use getters and setters to set object state, but the real problems mainly use the setters. You cannot make it immutable. Why? Because anyone can change the object after it’s created, which isn’t something you want to introduce into some of your programs. cases, you need that, but sometimes it shouldn’t be there. So inability sometimes we need something immediately, so this is the one way you can use the telescopic constructor.

However, some people used something known as a telescopic constructor. what does the telescopic constructor mean? You can have multiple constructors and each constructor can use other constructors depending on the parameters.

When to use Builder Design Pattern

  • This pattern can be used when involving in complex constructors.
  • When we want to make the class immutable.
  • When we have to construct a complex object which contains multiple optional parameters and the final step will return the object.

UML Diagram of Builder Design Pattern

source from : https://www.geeksforgeeks.org/builder-design-pattern/

Product class defines the type of the complex object.

Builder class defines all of the steps that must be taken in order to correctly create a product.

ConcreteBuilder classes contain the functionality to create a particular complex product.

Director class controls the algorithm that generates the final product object.

Builder pattern Implementation

In this section, we will use the real word example as Juice maker store. Suppose if a customer orders an orange juice then the shopkeeper takes three or four oranges, water, sugar, ice cubes etc. as an ingredients and grinds all these ingredients in a juicer and serve to the customer.

  1. create a Juice class. In this class we have declared five private variables (water, fruit, sugar, icecube and juicename).

2. We want to create a JuiceMaker class

3. We want to create two classes → OrangeJuice class and AppleJuice Class

4. Next we have created ShopKeeper class in which we have implemented takeorder () method with one argument as juiceType. In this method we defined that if customer orders orange juice then the shopkeeper will make orange juice. Similarly for apple juice order.

5. Finally, we have created Builder class in which we have implemented main method. Inside this main method we have created Juice class object such as orange and apple and called takeOrder() method of ShopKeeper class.

Output

Advantages of Builder Design pattern

  • It helps to minimize the number of parameters in the constructor. There is no need to pass in null for optional parameters to the constructor.
  • This pattern provides flexibility in design.
  • Object is always instantiated in a complete state.
  • The pattern provides good control over the construction procedure.
  • Immutable objects can be built without much complex logic in the object building process.

Disadvantages of Builder Design pattern

  • The number of lines of code increases at least to double in builder pattern, but the effort pays off in terms of design flexibility and much more readable code.
  • Requires creating a separate ConcreteBuilder for each different type of Product.

Examples of Builder Design pattern

StringBuilder and StringBuffer are some examples of Builder design pattern.

We have now come to the end of discussing some types of creative design patterns. Next, we will talk about some types of behavioral design patterns.

⭐️Chain of Responsibility Design Pattern

Chain of responsibility pattern is one type of the behavioral design pattern. This design pattern has more uses. but a lot of people don’t use it because they don’t know about it. We use this pattern to achieve loose coupling in our software design, where a request from the client is passed to a chain of objects to process them. The objects in the chain will choose who will handle the request after it has been received through a handler. If a particular object cannot handle that request, it will pass the request to the next object in that chain. Each of these objects contain certain types of commands to handle that type of request.

The Java API logger is the best example we can see of this chain of responsibility pattern implemented in practice.

When numerous objects may handle a request and there is no requirement that the handler be a particular object, this pattern is advised. Please be aware that an unhandled request is an acceptable use case. The handler is also chosen at runtime.

When to use the Chain of Responsibility Design Pattern

  • When Multiple objects may handle a request at runtime, and the handler isn’t known a priori.
  • When you want to decouple a request’s sender and receiver
  • When you don’t want to specify handlers explicitly in your code.
  • When you want to issue a request to one of several objects without specifying the receiver explicitly.

UML Diagram of Chain of Responsibility Design Pattern

resource taken from internet

Handler provides an interface to receive the request and dispatches the request to a chain of handlers. Also It has reference to the only first handler in the chain. It does not know anything about the rest of the handlers.

Concrete handlers : These are responsible for handle the requests they receive. If a particular handler cannot handle the request, it sends the request to its successor.

Client : Send an initial request and this will access the handler to handle it.

Chain of Responsibility Design Pattern Implementation

Let us see real world example for Chain of responsibility design pattern. Assume an example of Torrent Bill Payment Kasun where customers can pay their electricity bill instead of standing in the queue. If any customer wants to pay his electricity bill via kiosk then he has to enter their customer number and have to place their money in cash collector. Suppose the amount of money is 1965 then inside the Kasun 500 rupees handler performs operation and fetches two three notes of five hundred and passes the request to 100 rupees handler it performs operation and fetches two notes of one hundred. Similarly for 10 rupees handler it fetches four notes of ten rupees and 5 rupees handler it fetches one note of five rupees.

  1. We want to create RupeesHandler class

2. Next we want to create handler classes for 500,100,50,20 and 5 rupees.

3. Then we have to create a class for user →Kasun.java class

4. Finaly we have to create ChainOfResponsibility class. Inside the main method we created a object of Kasun Class and called payment () method using that object.

Finaly we get the rupees count for kasun’s payment like this:

Next we will discuss about the last pattern of this article.

⭐️Memento Design Pattern

Memento design Pattern is a Behavioral design pattern. It offers a solution to implement undoable actions. This will be done by saving the state of an object at a given instant and restoring it if the actions performed since need to be undone. If you want to develop an application, that has undo or rollback functionality, then you can go with memento pattern. Because it is a design pattern designed to implement that functionality at the right moment.

The Memento design pattern has three pillars known as: originator, caretaker, and Memento.

figure : UML of memento pattern from sourcemaking.com resource

The originator is the one that we need to maintain the state.

The caretaker is the one who keeps track of the originator. When we implement this originator, together with the memento and the past state, into the caretaker.

Memento is the object lock box that contains basic state storage and retrieval capabilities. Memento object is immutable and passes its data only once, through the constructor.

When to Use Memento Design Pattern

  • It is used in situations where some actions are undoable, therefore requiring to rollback to a previous state.

Some Real world example of memento pattern

  • It is used in code editors, we can revert or apply any code change with simple commands to undo and redo.
  • In calculator applications, we can revisit all the calculations in memory with simple button press.
  • In programming, memento can be used to create checkpoints during database transactions. If any operation fails, we just rollback everything to last known stable database state.
  • In Windows, we create restore points because we can use those to restore our OS into a previous state, if something breaks or system crashes.

Memento pattern Implementation

We will take a real world example for memento as create memento for a word document object which has four basic attributes as id, title, heading and description. WordDocumentMemento class is used as memento for word document objects.

In this above code, we have created a WordDocument class in which we have defined four variables id, title, heading, description. Also we have created WordDocument method with two parameters id and title in which super() method is called. Then we have created a memento for the WordDocument. Then a restore() method for the word document is created with four attributes id, title, heading, description.

We have created a final class WordDocumentMemento in which we have created four final variables id, title, heading and description. The function WordDocumentMemento with four parameters id, title, heading and description is used to get the values of the word document attributes. Then we created four methods getId(), getTitle(), getHeading(), getDescription() that returns the four attributes id, title, heading, description.

The above class MementoDesignPattern includes main() Class in which we create a word document object document. Then we set content for the document and restore the content of the same document using setContent() and restore() methods.

Output

In the output, initially we set the description of document as “My First Word Document” then on the second attempt we change the description to “My Second Word Document”. Then we restore the document description to the previous state.

References

https://www.youtube.com/watch?v=ubG_5_QnbkE&t=235s

https://examples.javacodegeeks.com/core-java/java-builder-design-pattern-example/

--

--