Is the decorator pattern really needed here?

I am learning the decorator design pattern from the Head first design patterns book. Their example treats different types of coffees as a Beverage. The beverages are decorated with things like milk, soy, whip cream etc. For example, the DarkRoast coffee with mocha and whip cream :&nbsp;<a href="https://i.stack.imgur.com/AaQQY.png" target="_blank"><img src="https://i.stack.imgur.com/AaQQY.png"></a>

I am learning the decorator design pattern from the Head first design patterns book. Their example treats different types of coffees as a Beverage. The beverages are decorated with things like milk, soy, whip cream etc. For example, the DarkRoast coffee with mocha and whip cream : 

The class diagram : 

I understand that this example is used only because it is simple. But, I have an alternate and simpler way to implement this example without decorator pattern. We can have an Item class with description and cost. Then, the Beverage class can have baseCost, totalCost and list of Items.

Does this alternative design have any major disadvantages over the decorator pattern ? Can you give any specific scenarios where the decorator pattern would be better than my design ?

PS - In case anyone wants to see the decorator code : https://github.com/bethrobson/Head-First-Design-Patterns/tree/master/src/headfirst/designpatterns/decorator/starbuzz

Design Patterns for Beginners with real-world Examples

Design Patterns for Beginners with real-world Examples

Design Patterns for Beginners with real-world Examples. When do you use Design Patterns? How do you implement different Design Patterns in Java? What are Design Patterns? Why do you use Design Patterns? What are the different types of Design Patterns? When do you use Design Patterns? What are the real-world examples for Design Patterns.

Design Patterns tutorial explained in simple words using real-world examples.

TABLE OF CONTENT

  • 0:00:00 Introduction
  • 0:01:40 What are Design Patterns?
  • 0:04:15 How to Take This Course
  • 0:05:50 The Essentials
  • 0:06:53 Getting Started with Java
  • 0:09:23 Classes
  • 0:13:34 Coupling
  • 0:15:34 Interfaces
  • 0:21:17 Encapsulation
  • 0:26:25 Abstraction
  • 0:30:33 Inheritance
  • 0:32:55 Polymorphism
  • 0:36:42 UML
  • 0:40:52 Memento Pattern
  • 0:42:43 Solution
  • 0:48:31 Implementation
  • 0:54:22 State Pattern
  • 0:59:46 Solution
  • 1:02:59 Implementation
  • 1:09:31 Abusing the Design Patterns
  • 1:11:18 Abusing the State Pattern

Design Patterns For Beginners — with Java Examples

Design Patterns For Beginners — with Java Examples

In this guide, we give you an introduction to the world of design patterns. For each pattern, we understand: the pattern, the context in which it is applicable  —  with a real world example.

You will learn

  • What are Design Patterns?
  • Why do you use Design Patterns?
  • What are the different types of Design Patterns?
  • When do you use Design Patterns?
  • How do you implement differnt Design Patterns in Java?
  • What are the real world examples for Design Patterns?

Software Design

This is the second article in a series of articles on Software Design:


  • 1 — How do you keep your design simple?
  • 2 — Design Patterns For Beginners — with Java Examples
  • 3 — What is Abstraction?
  • 4 — Encapsulation — with examples
  • 5 — Coupling — with examples
  • 6 — Cohesion — with examples
  • 7 — Introduction to Evolutionary Design

What Are Design Patterns?

We have been building object oriented software for over 40 years now, starting with Smalltalk, which was the first object oriented language.


The programming world has encountered a large number of problems, and a variety of solution have been proposed to tackle them.

An attempt was made by a group of four people, famously called the “Gang-Of-Four” or GoF, to come up with a set of common problems and solutions for them, in the given context.

This catalog of common problems and their solutions is labeled as GOF (Gang of Four) Design Patterns.

Why Design Patterns?

The advantages of design patterns are:


  • To provide standard terminology that everybody understands
  • Not to repeat the same mistakes over and over again

What Are The Types Of Design Patterns?

The design patterns we talk about here, are from the perspective of an object oriented world. There are mainly three different kinds of design patterns:


  • Creational Patterns
  • Structural Patterns
  • Behavioral Patterns

Creational

Creational patterns deal with creation of objects.


Structural

Structural patterns deal with the composition of objects.


It deals with questions such as:

  • What does a class contain?
  • What are the relationships of a class with other classes? Is it inheritance or composition?

Behavioral

Behavioral patterns focus more on the behavior of objects, or more precisely, interactions between objects.


How does an object communicate with another object?

Exploring Creational Design Patterns

We explore the following creational design patterns:


The Prototype Pattern

A Prototype represents a fully initialized instance, to be copied or cloned.

Let’s take an example:

Let’s consider the design of a Chess game. Every game of Chess has the same initial setup — The King, Queen, Rook, Bishop, Knight and the Pawns all have their specific places. Let’s say we want to build software to model a Chess game.

Every time a new Chess game is played, we need to create the initial board layout.

Instead of repeating the creation of chess board each time

  • We can create an object that contains the initial setup
  • Clone from it — each time a new Chess game is played.

The object with the initial setup of the chess board is the prototype. And, we are using the prototype pattern.

Isn’t it simple?

In the Prototype pattern, you have a fully initialized instance — here, the initial board layout — that is readily available.

Whenever a new Chess game is started — for example, in any of the numerous online Chess portals — this initialized instance is merely copied, or cloned.

The Builder Pattern

The Builder Pattern separates object construction from its representation. What does that mean?


Assume that you go out for a multi- course dinner to a Restaurant. Such a dinner would have many options, such as Starters, Main course and Desserts. You would probably choose two or three out of the presented options. A particular client may want to have dinner with the first two options only, leaving out the Desserts option. Yet another would prefer the Main course and Desserts, skipping the Starters entirely.

Similar situations might arise in designing software. You may need to build an object using a subset of the options that are available — or, create the object in multiple ways. This is where the Builder pattern comes in handy.

To understand it further, let’s look at a small piece of code.

Let’s say you’re writing software for a machine that prepares coffee. The main ingredients of coffee are coffee, milk and sugar.

Dependending from which part of the world you are from, you choose whether or not you have sugar and milk.

The Builder pattern steps in to provide these Coffee creation options for you.

Have a look at the code inside main().

What we have inside the Coffee is a Builder, to which we pass the mandatory type of the coffee. Chained to that call, we make other calls adding in our preferences of the other ingredients.

Someone else who wants a different coffee can easily build it. This leads to a huge amount of flexibility in building objects.

Other approaches to solving this problem, such as the use of setters, have many inherent problems. These solution lead to code that is difficult to read, and also behave erratically in multithreaded programs. The Builder pattern solves all those problems.

The advantages of using the Builder pattern are:

  • It simplfies object creation
  • Leads to more readable code
  • Does not allow the values to be modified

The Singleton Pattern

The Singleton pattern is the most famous among all the design patterns. What this pattern does is very clear from its name — allow only one instance of a class per JVM at any point in time.


A good real world comparison would probably be the President of a Nation.

However, there is a disclaimer here — there can only be one instance of that class, per JVM. If you have a Java application that runs as part of a cluster of application servers, each server runs a separate JVM instance. Therefore, you are allowed to have one instance of the Singleton created on each application server, at any given point of time.

There are a few things to remember whenever you create a Singleton class.

  • The constructor needs to be private, to prevent the possibility of other objects creating instances of your class.
  • In Java, build a Singleton using an Enum.
  • JEE 7 has a built in annotation named @Singleton, along with other related annotations.
  • The main disadvantage of using the Singleton pattern is that the resulting code is difficult to unit test. Make clear decision as to where you absolutely need to use a Singleton, and where you don’t.
  • In frameworks such as Spring, the objects that are managed are called beans, and beans are Singletons by default. What Spring does well is to ensure all this is in the background.

The Factory Method Pattern

The intent of the Factory Method pattern is to create a family of object types. Let’s look at a code example.

This code implements a PersonFactory. This class has a static method named getPerson() that accepts a person’s name and gender as parameters. Depending on the gender String passed in, it either returns a Male or a Female object.

If somebody wants to create a male person, they invoke the getPerson()method on the PersonFactory with an gender argument of "M". Similarly, you can create a female person by invoking the getPerson() method on the PersonFactory with an gender argument of "F".

We are passing in an identifier of the the type of object we need, at the time of creation, while still referring to the generic type, Person.

The Male and Female classes are hidden behind the PersonFactoryimplementation.

The advantage of using the Abstract Method pattern is that you can add additional types to the factory, without much change in the other classes using this class. In our example, you can add more types of gender, without affecting the existing code that deals with other genders, which all use Person.

What about the complexity involved in creating an object?

It greatly simplifies the task of object creation. The PersonFactory makes the decision of what object to create, and delivers it to us.

Do check out our video on the same topic:

Structural Design Patterns

Let us now have a look at the structural design patterns we want to explore.


The Proxy Pattern

A Proxy is an object that represents another object.

Let’s look at a real world example.

Your debit card is a proxy for your bank account. Whenever you make a transaction using a debit card, the corresponding money is deducted from the bank account.

The debit card is a proxy for your bank account, which is the actual object.

Similar to that, in programming you might have to program interactions with remote objects. In such situations, you create a proxy object that takes care of all external communications. You would communicate with the proxy as if it were residing on your local machine.

A good example are the EJB Home and Remote interfaces.

A proxy hides the complexity involved in communicating with the real object.

The Decorator Pattern

The Decorator pattern allows us to add responsibilities to objects, dynamically.


In object oriented programming, we typically use a lot of inheritance.

Example 1

Let’s say a particular Pizza outlet has 10 types of pizza. Our implementation has 10 classes for these Pizza types.

Now there is a requirement to make these pizzas available with 3 types of toppings. If we would want to create individual classes for each pizza and topping combination, we have a total of 30 classes to manage.

Instead of doing this, can we make the pizza-topping relationship dynamic? Can we add a topping on top of an existing pizza?

We need to use a topping as a decorator on top of any pizza.

Example 2

Another example would be the adding a discount on a pizza order.

Let’s say, you have an order, and based on some criteria, you want to offer a discount to the customer. There might be a variety of discounts which might be applicable at different times. If you add a different type of a discount to each type of order, then in a static relationship, you need to maintain hundreds of classes.

Treating a discount as a decorator on an order makes the relationship dynamic.

Example 3

A very good example where the Decorator pattern is implemented in Java is the Java I/O packages. This is reflected in the way we create an input stream in an I/O program:

You have a FileInputStream. If you want to make it buffered, then add a decorator to it in the form of a BufferedInputStream. If you want the buffered FileInputStream to have line numbers in addition, then add a decorator for a LineNumberInputStream.

Summary

Decorator Pattern enables you to add behavior to existing objects, at run time. This allows the user of the interface to decide, how he/she wants to create the objects.

The drawback of this approach is the complexity involved in creating objects. The user needs to understand a lot of classes and their relationships before being able to use the power of the Decorator.

The Facade Pattern

A Facade is a single class that represents an entire subsystem.

Let’s take the example of an event manager. An event manager is the go-to person when you want to organize an event. He/She would handle several aspects of an event such as the decorations, the food, sending out invitations to guests, the music arrangements, and similar things. The event manager acts as the facade of the event organization subsystem.

Consider the case of a distributed system. You typically have the need for multiple calls, across layers.

Take for instance, a system that offers the service for online book orders. Whenever an order comes in, several things need to be taken care of, such as checking for the stock, reserving the order, accepting the payment, updating the stock, and generating the invoice.

We can create a single facade, such as the order interface, which would manage all incoming orders and provide an interface to the customer.

The advantage of using the Facade pattern is that it reduces the number of network calls, as well as reduces coupling among classes.

It succeeds in establishing a transaction boundary between communicating objects. Facades, like services, are good hubs to implement transactions.

As long as the interface of the facade remains the same, the implementation details of the subsystem can change.

The Adapter Pattern

An Adapter is used to match interfaces of different classes.


Let’s take the real world example of power adapters.

Problem : If you buy a mobile phone in India, it comes with a charger that only works with power sockets used in India. If you take the same charger to the US for example, it will not work, as it will not fit into sockets there.

Solution : The solution is to use a travel adapter, to use with your charger when you travel. You can plug in your charger into the travel adapter, and the travel adapter is used to connect to the socket in a particular country.

Similarly, when you try to talk to a system that uses a different message format or a language, you need an adapter to translate messages.

An interesting example is communication between a Java program and a web service. Before sending out the data to the service, we need to convert the object into XML or JSON format. We are implementing the Adapter pattern!

The Flyweight Pattern

Let’s consider a few scenarios


  • Creation of an object takes a lot of time and involves multiple instances
  • Each instance of an object occupies a lot of memory
  • Some objects might be used several times across same application with same values

In these scenarios, you might not want to create a new instance everytime it is needed.

How about caching an instance and reusing it when needed?

A Flyweight represents creating a fine-grained instance, that is being used for efficient sharing.

Example 1

A really good real work example is the public switched telephone network (PSTN).

In the PSTN, there are always a limited number of lines, and for simplicity, let’s assume this number is 10. However, there are thousands of customers that use these lines. Since all 1000 customers would not make calls at about the same time, it is possible to efficiently switch calls coming in, among the existing 10 lines.

Example 2

In the software world, a good example of Flyweight pattern is JDBC connections.

A connection pool is a set of connections to the database. The application may be firing a lot of queries, but we don’t create a new connection whenever a new query comes in. As soon as a query comes in, we match it to an available connection, and the query gets fired. Once query execution is done, the connection is released back into the pool.

Using such a pool allows us to avoid the cost involved in creating and closing a connection.

Behavioral Design Patterns

Let us now have a look at the behavioral design patterns.


The Chain Of Responsibility Pattern

The Chain Of Responsibility Pattern represents a way of passing a request between a chain of objects.

Example 1

The best example of this pattern can be seen in the exception handling mechanism of most programming languages.

Suppose you have a method1() calling method2(), and method2() in turn calls method3(). Assume that method3() throws an exception.

If method3() has no exception handling, then the exception is passed on to method2()to handle it. If again method2() has no exception handling inside it, then the exception is passed on to method1(). If even method1() cannot handle it, it get thrown out of method1() as well.

Example 2

Consider a real world example of a loan approval process.

A bank clerk has permissions to approve loans within a certain amount. If the amount goes above that, then it goes to the supervisor. The supervisor has a similar, albeit larger loan approval limit set for him. If the loan amount exceeds that limit, then it goes to his supervisor, and so on.

Summary

With Chain Of Responsibility, we have a chain of objects already ready, that wait to process requests. When a new request enters the system, it goes to the first object in the chain to attempt processing. Depending on the processing condition, the request travels up the chain and gets fully processed at some level, or maybe not processed at all.

The Iterator Pattern

The Iterator pattern is one of the most simple design patterns. You have a set of elements arranged in a collection, and you want to sequentially access those elements. A good example of an Iterator is a TV remote, which has the “next” and “previous” buttons to surf TV channels. Pressing the “next” button takes me one channel in the forward direction, and pressing the “previous” button takes me one channel in the backward direction.

In the programming works, examples of the Iterator class and the enhanced for loop in Java are examples of the Iterator pattern.

The State Pattern

The State Pattern is used to alter an object’s behavior when its state changes.


Take a look at this Java example:

Let’s take the example of a fan wall control. The fan wall control controls the speed with with a fan rotates. It has speed levels ranging from 0 to 5. When it is at level 0, the fan does not rotate, and it rotates the fastest at level 5.

When you rotate the knob of the fan control, the level changes, and this causes the speed of the fan to change as well. This is a classic case of a change in state (level) causing a change in behavior (speed).

FanwallControl object is composed of a SpeedLevel object. SpeedLevel is an interface that has four different implementations. Initially, the level is at Off, and when yuo click rotate at that time, the new speed is at SpeedLevel1. The happens successively, and if you rotate at SpeedLevel3, the level returns to Off.

In case you need to define an additional speed level, just add in a new class that implements the SpeedLevel interface, and implement its rotate method.

This is an excellent example that highlights the advantages of an extensible class.

The Strategy Pattern

The strategy has the task of encapsulating an algorithm inside a class. Let’s look at a Java code example:

The class ComplexClass intends to perform a lot of complex logic within it. One part of that logic is to sort a set of values. One direct way would be to implement the entire sorting logic within ComplexClass. This would make it very inflexible, since if you wanted to change the sorting logic tomorrow, that entire code needs to change.

When we use the Strategy pattern, we separate the algorithm of how the sorting is done, from ComplexClass.

We define an interface named Sortable, which has a method named sort(). Any actual sort algorithm is an implementation of Sortable, and needs to override sort()method.

Now, ComplexClass is given a particular Sortable implementation as a constructor argument. ComplexAlgorithm does not care what exact sorting algorithm is being used; it is happy that that object implements the sort()method of Sortable.

A lot of flexibility results due to the use of the Strategy pattern. You can dynamically change the strategy, and pass in the right one according to the context.

The Observer Pattern

The Observer pattern is a way of notifying a change, to a number of classes.


If you are a fan of cricket, you may want to know whenever Sachin Tendulkar scores a century, so that you can celebrate.

All such similar people would register themselves to the event of Sachin scoring a century. Each of these people is now an Observer for that event. Whenever Sachin does score a century, a centralized program will notify each observer.

Another example is that of online bidding. A group of bidders at an auction register themselves to receive notifications when a higher bid is placed. As soon as a bid higher than the current one is placed, all the registered bidders get to know about it.

There are two main parts to implementing the Observer design pattern.

  • Registration — where the interested objects register themselves with the centralized program to receive notifications
  • Notification — where the registered observers receive notifications from the centralized program

Here is a simple implementation of the Observer pattern:

We have created an instance of SachinCenturyNotifier, and registered three fans with it.

Whenever Sachin scores a century, the call notifier.sachinScoredACentury()would be made, and all three fans would be notified.

The Visitor Pattern

The Visitor pattern allows us to add a new operation to a class, without changing the class.


There are a lot of scenarios when designing frameworks, where we don’t want other people to modify the code in the framework. We want others to extend the functionality without touching the framework code. They are allowed to add new operations, but not to change the existing operations.

The Visitor pattern allows you to do this.

A good real world example of the Visitor pattern is the operation of a taxi company.

As soon as a person calls a taxi company, and a cab is dispatched, the company accepts a visitor. Once the visitor, or customer enters the taxi, he is no longer in control of where he is going. The cab driver is now in control.

If we look at it as object oriented code, the driver class is in control of the customer class. The driver class can add new operations on top of the customer/visitor.

The Template Method Pattern

The Template Method pattern is used to defer the exact steps of an algorithm, to a subclass.


A good real world example of this pattern is how we go about creating a house plan. Any good house plan consists of a floor plan, the foundation, plumbing, framing and wiring. Such a plan is almost identical for each house.

If you were to model this in software, you could create a template class with this standard behavior defined. A subclass could extend this and give actual implementations. Such details could include the wooden flooring type, the wall paint colors, and any added wings as required.

A god example of the Template Method pattern is within the Spring framework, in the form of AbstractController:

handleRequest() merely takes care of the basic things. However, it leaves the lions share for the implementation to the method handleRequestInternal(). This method is defined by sub classes, where more specific logic can be implemented.

The Template Method pattern is all about doing the high level steps, and leaving the low level details to the sub classes. The sub classes can override the low steps and provide their own implementation.

The Command Pattern

The Command pattern encapsulates a command request as an object.


Let’s take a real world example.

Consider the scenario when a customer goes to a restaurant and wants to place an order for a meal. The writer merely writes the order he gets on a piece of paper, and passes it on to the chef. The chef executes the order, and then prepares the meal. He passes the piece of paper to the manager.

The verbal order from the customer has now become a paper object. This piece of paper is the command object. The command object contains all the details needed to execute the request.

Similarly in object oriented programming, we can encapsulate all the details of a request into an object, and pass that object to execute it.

In web applications, when a user types in the details on a form, these details are captured in a single request object, which is then passed across.

The interface java.lang.Runnable is also a good example of how this pattern is implemented. We create threads in Java by extending the Runnableinterface, which has all the logic for execution in its start() method. When we want to create and start a thread, we pass this class to the start()method.

The Memento Method

The Memento pattern captures and later restores an object’s internal state.


A lot of games that we play offer the option of performing an intermediate save. At a certain point in the game, you can save it and later come back to it.

To implement this, we need to save the internal states of the game objects, and restore them at a certain point in time.

This save-revert functionality can be implemented by using serialization in a language such as Java.

The memento pattern is very useful implementing undo/redo operations.

For example, if you are working on a text document in a word processor. If at a certain point, you decide to undo changes, you can see each undo until you reach a point where you are satisfied. You have now reverted to an earlier saved state of the document.

The Mediator Pattern

The Mediator pattern is used to define simplified communication between classes.


Take the example of an Air Traffic Controller (ATC). Let’s say that at any point of time in India, we have about 500 flights in air. We need to decide the routes that each of these flights needs to take. This also includes deciding the times at which each of these flights takes off and lands. It would be a highly complex situation if each of these 500 flights needs to talk with each other and arrive at an acceptable schedule of routes.

That’s why we have the concept of an ATC. The flights communicate with the ATC, and having assimilated the information from all the flights, the ATC makes the decisions and communicates them back the flights.

In the software world, a good example of the Mediator pattern is the ESB (Enterprise Service Bus). In a distributed system, instead of letting the applications talk to each other, an application drops in a message to the ESB. The ESB routes the request to the application that needs to handle the request. It acts as the Mediator.

Do check out our video on the same topic:

Summary

In this article, we had an quick look over a variety of design patterns.

A design pattern is an approach to solve a problem in a given context. We focused on understanding the context in which a particular pattern may be applicable with real world examples.

Thanks for reading ❤

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Learn More

Java Programming Masterclass for Software Developers

Selenium WebDriver with Java -Basics to Advanced+Frameworks

Java In-Depth: Become a Complete Java Engineer!

JSP, Servlets and JDBC for Beginners: Build a Database App

JSP, Servlet, JSLT + Hibernate: A complete guide

Top 5 Java Test Frameworks for Automation in 2019

Spring Boot + JPA + Hibernate + Oracle

Learn Java - Java Basics Tutorial for Beginners

50+ Java Interview Questions for Programmers

The Future of Java - Project Amber

Originally published on https://medium.com/

The Basic Design Patterns All Developers Need to Know in 2020

The Basic Design Patterns All Developers Need to Know in 2020

The Basic Design Patterns All Developers Need to Know. What is a Design Pattern? There are about 26 Patterns currently discovered. In this post, you'll see the 3 types of Design Patterns all Developers should know: Creational, Structural and Behavioral. We will go through one basic design pattern for each classified type.

What is a Design Pattern?

Design patterns are design level solutions for recurring problems that we software engineers come across often. It’s not code - I repeat,❌CODE. It is like a description on how to tackle these problems and design a solution.

Using these patterns is considered good practice, as the design of the solution is quite tried and tested, resulting in higher readability of the final code. Design patterns are quite often created for and used by OOP Languages, like Java, in which most of the examples from here on will be written.

Types of design patterns

There are about 26 Patterns currently discovered (I hardly think I will do them all…).

These 26 can be classified into 3 types:

1. Creational: These patterns are designed for class instantiation. They can be either class-creation patterns or object-creational patterns.

2. Structural: These patterns are designed with regard to a class's structure and composition. The main goal of most of these patterns is to increase the functionality of the class(es) involved, without changing much of its composition.

3. Behavioral: These patterns are designed depending on how one class communicates with others.

In this post, we will go through one basic design pattern for each classified type.

Type 1: Creational - The Singleton Design Pattern

The Singleton Design Pattern is a Creational pattern, whose objective is to create only one instance of a class and to provide only one global access point to that object. One commonly used example of such a class in Java is Calendar, where you cannot make an instance of that class. It also uses its own getInstance()method to get the object to be used.

A class using the singleton design pattern will include,

  1. A private static variable, holding the only instance of the class.
  2. A private constructor, so it cannot be instantiated anywhere else.
  3. A public static method, to return the single instance of the class.

There are many different implementations of singleton design. Today, I’ll be going through the implementations of;

1. Eager Instantiation

2. Lazy Instantiation

3. Thread-safe Instantiation

Eager Beaver ?️

public class EagerSingleton {
	// create an instance of the class.
	private static EagerSingleton instance = new EagerSingleton();

	// private constructor, so it cannot be instantiated outside this class.
	private EagerSingleton() {  }

	// get the only instance of the object created.
	public static EagerSingleton getInstance() {
		return instance;
	}
}

This type of instantiation happens during class loading, as the instantiation of the variable instance happens outside any method. This poses a hefty drawback if this class is not being used at all by the client application. The contingency plan, if this class is not being used, is the Lazy Instantiation.

Lazy Days ?

There isn’t much difference from the above implementation. The main differences are that the static variable is initially declared null, and is only instantiated within the getInstance() method if - and only if - the instance variable remains null at the time of the check.

public class LazySingleton {
	// initialize the instance as null.
	private static LazySingleton instance = null;

	// private constructor, so it cannot be instantiated outside this class.
	private LazySingleton() {  }

	// check if the instance is null, and if so, create the object.
	public static LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
}

This fixes one problem, but another one still exists. What if two different clients access the Singleton class at the same time, right to the millisecond? Well, they will check if the instance is null at the same time, and will find it true, and so will create two instances of the class for each request by the two clients. To fix this, Thread Safe instantiation is to be implemented.

(Thread) Safety is Key ?

In Java, the keyword synchronized is used on methods or objects to implement thread safety, so that only one thread will access a particular resource at one time. The class instantiation is put within a synchronized block so that the method can only be accessed by one client at a given time.

public class ThreadSafeSingleton {
	// initialize the instance as null.
	private static ThreadSafeSingleton instance = null;

	// private constructor, so it cannot be instantiated outside this class.
	private ThreadSafeSingleton() {  }

	// check if the instance is null, within a synchronized block. If so, create the object
	public static ThreadSafeSingleton getInstance() {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
		return instance;
	}
}

The overhead for the synchronized method is high, and reduces the performance of the whole operation.

For example, if the instance variable has already been instantiated, then each time any client accesses the getInstance() method, the synchronized method is run and the performance drops. This just happens in order to check if the instance variables’ value is null. If it finds that it is, it leaves the method.

To reduce this overhead, double locking is used. The check is used before the synchronized method as well, and if the value is null alone, does the synchronized method run.

// double locking is used to reduce the overhead of the synchronized method
public static ThreadSafeSingleton getInstanceDoubleLocking() {
	if (instance == null) {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
	}
	return instance;
}

Now onto the next classification.

Type 2: Structural - The Decorator Design Pattern

I’m gonna give you a small scenario to give a better context to why and where you should use the Decorator Pattern.

Say you own a coffee shop, and like any newbie, you start out with just two types of plain coffee, the house blend and dark roast. In your billing system, there was one class for the different coffee blends, which inherits the beverage abstract class. People actually start to come by and have your wonderful (albeit bitter?) coffee. Then there are the coffee newbs that, God forbid, want sugar or milk. Such a travesty for coffee!! ??

Now you need to have those two add-ons as well, both to the menu and unfortunately on the billing system. Originally, your IT person will make a subclass for both coffees, one including sugar, the other milk. Then, since customers are always right, one says these dreaded words:

“Can I get a milk coffee, with sugar, please?”

???

There goes your billing system laughing in your face again. Well, back to the drawing board….

The IT person then adds milk coffee with sugar as another subclass to each parent coffee class. The rest of the month is smooth sailing, people lining up to have your coffee, you actually making money. ??

But wait, there’s more!

The world is against you once again. A competitor opens up across the street, with not just 4 types of coffee, but more than 10 add-ons as well! ?

You buy all those and more, to sell better coffee yourself, and just then remember that you forgot to update that dratted billing system. You quite possibly cannot make the infinite number of subclasses for any and all combinations of all the add-ons, with the new coffee blends too. Not to mention, the size of the final system.??

Time to actually invest in a proper billing system. You find new IT personnel, who actually knows what they are doing and they say;

“Why, this will be so much easier and smaller if it used the decorator pattern.”

What on earth is that?

The decorator design pattern falls into the structural category, that deals with the actual structure of a class, whether is by inheritance, composition or both. The goal of this design is to modify an objects’ functionality at runtime. This is one of the many other design patterns that utilize abstract classes and interfaces with composition to get its desired result.

Let’s give Math a chance (shudder?) to bring this all into perspective;

Take 4 coffee blends and 10 add-ons. If we stuck to the generation of subclasses for each different combination of all the add-ons for one type of coffee. That’s;

(10–1)² = 9² = 81 subclasses

We subtract 1 from the 10, as you cannot combine one add-on with another of the same type, sugar with sugar sounds stupid. And that’s for just one coffee blend. Multiply that 81 by 4 and you get a whopping 324 different subclasses! Talk about all that coding…

But with the decorator pattern will require only 16 classes in this scenario. Wanna bet?

If we map out our scenario according to the class diagram above, we get 4 classes for the 4 coffee blends, 10 for each add-on and 1 for the abstract component and 1 more for the abstract decorator. See! 16! Now hand over that $100.?? (jk, but it will not be refused if given… just saying)

As you can see from above, just as the concrete coffee blends are subclasses of the beverage abstract class, the AddOn abstract class also inherits its methods from it. The add-ons, that are its subclasses, in turn inherit any new methods to add functionality to the base object when needed.

Let’s get to coding, to see this pattern in use.

First to make the Abstract beverage class, that all the different coffee blends will inherit from:

public abstract class Beverage {
	private String description;

	public Beverage(String description) {
		super();
		this.description = description;
	}

	public String getDescription() {
		return description;
	}

	public abstract double cost();
}

Then to add both the concrete coffee blend classes.

public class HouseBlend extends Beverage {
	public HouseBlend() {
		super(“House blend”);
	}

	@Override
	public double cost() {
		return 250;
	}
}

public class DarkRoast extends Beverage {
	public DarkRoast() {
		super(“Dark roast”);
	}

	@Override
	public double cost() {
		return 300;
	}
}

The AddOn abstract class also inherits from the Beverage abstract class (more on this below).

public abstract class AddOn extends Beverage {
	protected Beverage beverage;

	public AddOn(String description, Beverage bev) {
		super(description);
		this.beverage = bev;
	}

	public abstract String getDescription();
}

And now the concrete implementations of this abstract class:

public class Sugar extends AddOn {
	public Sugar(Beverage bev) {
		super(“Sugar”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Mocha”;
	}

	@Override
	public double cost() {
		return beverage.cost() + 50;
	}
}

public class Milk extends AddOn {
	public Milk(Beverage bev) {
		super(“Milk”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Milk”;
	}

	@Override  public double cost() {
		return beverage.cost() + 100;
	}
}

As you can see above, we can pass any subclass of Beverage to any subclass of AddOn, and get the added cost as well as the updated description. And, since the AddOn class is essentially of type Beverage, we can pass an AddOn into another AddOn. This way, we can add any number of add-ons to a specific coffee blend.

Now to write some code to test this out.

public class CoffeeShop {
	public static void main(String[] args) {
		HouseBlend houseblend = new HouseBlend();
		System.out.println(houseblend.getDescription() + “: “ + houseblend.cost());

		Milk milkAddOn = new Milk(houseblend);
		System.out.println(milkAddOn.getDescription() + “: “ + milkAddOn.cost());

		Sugar sugarAddOn = new Sugar(milkAddOn);
		System.out.println(sugarAddOn.getDescription() + “: “ + sugarAddOn.cost());
	}
}

The final result is:

It works! We were able to add more than one add-on to a coffee blend and successfully update its final cost and description, without the need to make infinite subclasses for each add-on combination for all coffee blends.

Finally, to the last category.

Type 3: Behavioral - The Command Design Pattern

A behavioral design pattern focuses on how classes and objects communicate with each other. The main focus of the command pattern is to inculcate a higher degree of loose coupling between involved parties (read: classes).

Uhhhh… What’s that?

Coupling is the way that two (or more) classes that interact with each other, well, interact. The ideal scenario when these classes interact is that they do not depend heavily on each other. That’s loose coupling. So, a better definition for loose coupling would be, classes that are interconnected, making the least use of each other.

The need for this pattern arose when requests needed to be sent without consciously knowing what you are asking for or who the receiver is.

In this pattern, the invoking class is decoupled from the class that actually performs an action. The invoker class only has the callable method execute, which runs the necessary command, when the client requests it.

Let’s take a basic real-world example, ordering a meal at a fancy restaurant. As the flow goes, you give your order (command) to the waiter (invoker), who then hands it over to the chef(receiver), so you can get food. Might sound simple… but a bit meh to code.

The idea is pretty simple, but the coding goes around the nose.

The flow of operation on the technical side is, you make a concrete command, which implements the Command interface, asking the receiver to complete an action, and send the command to the invoker. The invoker is the person that knows when to give this command. The chef is the only one who knows what to do when given the specific command/order. So, when the execute method of the invoker is run, it, in turn, causes the command objects’ execute method to run on the receiver, thus completing necessary actions.

What we need to implement is;

  1. An interface Command
  2. A class Order that implements Command interface
  3. A class Waiter (invoker)
  4. A class Chef (receiver)

So, the coding goes like this:

Chef, the receiver

public class Chef {
	public void cookPasta() {
		System.out.println(“Chef is cooking Chicken Alfredo…”);
	}

	public void bakeCake() {
		System.out.println(“Chef is baking Chocolate Fudge Cake…”);
	}
}

Command, the interface

public interface Command {
	public abstract void execute();
}

Order, the concrete command

public class Order implements Command {
	private Chef chef;
	private String food;

	public Order(Chef chef, String food) {
		this.chef = chef;
		this.food = food;
	}

	@Override
	public void execute() {
		if (this.food.equals(“Pasta”)) {
			this.chef.cookPasta();
		} else {
			this.chef.bakeCake();
		}
	}
}

Waiter, the invoker

public class Waiter {
	private Order order;

	public Waiter(Order ord) {
		this.order = ord;
	}

	public void execute() {
		this.order.execute();
	}
}
You, the client
public class Client {
	public static void main(String[] args) {
		Chef chef = new Chef();

		Order order = new Order(chef, “Pasta”);
		Waiter waiter = new Waiter(order);
		waiter.execute();

		order = new Order(chef, “Cake”);
		waiter = new Waiter(order);
		waiter.execute();
	}
}

As you can see above, the Client makes an Order and sets the Receiver as the Chef. The Order is sent to the Waiter, who will know when to execute the Order (i.e. when to give the chef the order to cook). When the invoker is executed, the Orders’ execute method is run on the receiver (i.e. the chef is given the command to either cook pasta ? or bake cake?).

Quick recap

In this post we went through:

  1. What a design pattern really is,
  2. The different types of design patterns and why they are different
  3. One basic or common design pattern for each type

I hope this was helpful.

Find the code repo for the post, here.