Design Patterns: the ignored terrain!

Smit Srivastava
Feb 21 · 7 min read

This article covers what design pattern is and its different categories with one example.

Source: Pexel by Iva Muskic

Recently, I mentioned to someone who is a software developer that I am reading an article on Design Patterns. And the look I got was — What’s that? I checked with few other developers and the responses were more or less similar. To cut the long story short, I came to know that many developers are not aware of the design patterns concept at all or have just heard the terms or confuse them with design principles. Disclaimer: I am talking about developers with experience of less than 3–4 years, and it’s not true for all developers. So, I thought I will write a primer on the design patterns. This article is going to be very basic and we will not dive deep into any of the patterns.

What is a Design Pattern?

Throughout our careers in software engineering, we all have seen similar kinds of design problems occurring again and again. Many times we started with one approach to solving it and then later found out an issue with that approach and then tried another and so on. After few iterations, we finalized an approach that was ideal for the given scenario. We are not the first ones to face this problem neither we are the first ones to solve it. Experts in the industry over the period faced similar kinds of recurring design problems and they developed a standard solution for the same. A design pattern is nothing but a practical proven solution to a recurring design problem. It allows us to use previously outlined solutions that expert developers have often used to solve a software problem so that we do not need to build a solution from the basics of object-oriented programming principles every time. These also help in providing structure to the code and avoid ‘spaghetti code’. It’s important to understand these are not a set of source code that one can memorize and put in their software like a java library or framework. Instead, these are more conceptual. We can take the chess analogy to understand it better. Knowing the rules of chess is like knowing the syntax and elements of a software language for example writing loops, creating classes, etc. As a novice, our main focus remains on the rules of chess and then the next step usually is to think about the next moves. However, if we gain experience in chess or if we observe an expert player, he/she is not thinking these things (these becomes first nature to them) but looking out for specific patterns in the board. There are many known patterns such as the exposed king or the isolated pawns etc. An experienced player will be able to know which patterns to create in what situation of the game and then will be able to exploit the same. It’s the same for the software design patterns too! It’s about knowing the patterns and then recognizing which patterns will fit in the given situations. The first part is the easy one. However, the second part comes with experience. Because there are various design patterns and many times multiple patterns can be applied but not all will be the best one to be used.

Benefits

Benefits are obvious:

  • No re-inventing the wheel. Experts have already done that we don’t need to go through trials again.
  • Better structured codes/designs: As developed by experts and went through iterations over the years. These are well structured, to say the least.
  • It helps to create a common design vocabulary: This means that design patterns provide a simplified means of discussing design solutions. So that they do not need to be explained over and over. Design patterns give pattern names, making it easier to discuss them. This saves time and ensures that everyone is referring to the same pattern. For example, there is a very common design problem in the software where we have two objects. The first object depends upon the second object. If the second object changes the first object needs to be notified. If we have to explain every time this problem statement and solution to this then it will take lots of time. Instead, we can simply say we will use ‘observer design pattern’ here. And everyone will know what it means. This also leaves less room for misunderstanding

One of the most famous books on design patterns is Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. These four are also called the gang of four. When each had developed programs and graphical applications, they had discovered patterns emerging in their design solutions. They formalized those patterns into a reference, which became their book. The patterns developed by the Gang of Four were organized to be readable and often named after their purpose. The grouping of patterns together forms a catalog, otherwise known as the Gang of Four’s design pattern catalog.

Categories of Patterns:

The Gang of Four’s pattern catalog contains twenty-three patterns. These patterns can be sorted into three different categories: creational patterns, structural patterns, and behavioral patterns. This categorization is not hard and fast. Some patterns can span to multiple or all categories.

Creational Patterns: It tackles how we handle creating new objects. It includes both creation and cloning. There are several different patterns based upon creating and cloning objects. For example, if we are creating an object that is similar to an existing one, instead of instantiating a new object, we might clone existing objects. We might choose to clone, rather than instantiate based upon the language we are implementing in. Languages without the notion of classes would encourage us to clone and add to existing objects. Language like Javascript does not contain traditional classes to be instantiated. Objects are instead cloned and expanded to meet the purposes of those particular instances, called prototypes. Javascript allows for changes to these prototypes at run time. Languages like Java and C# on the other hand, rely heavily on instantiating objects using specific classes defined at compile time. The different ways of creating objects can strongly impact how we solve a problem. Different languages, therefore, impact what patterns are possible to use.

Structural Patterns: describes how objects are connected to each other. These patterns relate to the design principles of decomposition and generalization. There are many different ways one can structure objects depending on the relationship one would like between them. Not only do structural patterns describe how different objects have relationships, but also how subclasses and classes interact through inheritance. Structural Patterns use these relationships and describe how they should work to achieve a particular design goal.

Behavioral patterns: focus on how objects distribute work and describe how each object does a single cohesive function. Behavioral patterns also focus on how independent objects work towards a common goal. In a formula-1 race, pit crew at the track is something very similar to this. Each member has a role to perform — changing the tire, un-mounting, mounting bolts, etc. but together they have one goal.

Singleton Design Pattern:

We will take one simple design pattern and will discuss it briefly. We will cover it in detail in the next article. Here the idea is to just give an understanding of a design pattern.

We will take Singleton Pattern. It’s a creational pattern. The Singleton pattern refers to having only one object of a class.

  • In some cases having multiple objects of a class can cause conflicts. In such cases, we go for the singleton pattern.
  • Another goal of the singleton pattern is that the single object is globally accessible within the program.

If we are working alone or on a small project, we can make a comment or mental note — we are not supposed to create multiple objects of the xyz class. But more often than less, we all will be working on a project where multiple developers will be working. Also, one can leave the company and the new person has no clue about it. So, it’s better to codify this design intent in the software itself. We will go over the actual Java code in the next article. However, just to have a better understanding we will briefly discuss how to do the same. If we create a ‘Private’ constructor in the class will it solve the problem? It does solve the problem that it can’t be called from outside the class. But this will also prevent creating an object of the class. To solve this we will do two things -

  • first, we will declare the ‘Private’ class variable. This class variable will refer to the one instance of our Singleton class. As the variable is private, it can only be modified within the class.
  • Second, create a public method in the class that will create an instance of this class, but only if an instance does not exist already.

As the method is public it can be called globally and can be used to create one instance of the class. The regular constructor is hidden. Other classes will call the public method. This puts the basic gatekeeping and ensures only one object is created. The same method can be used globally to refer to the object if it’s already created. One advantage of this is Lazy creation. That means an object is not created until it is needed. It has its trade-off but here we just wanted to discuss what it is.

I hope this article was able to give some idea about the concept of design patterns. It’s a vast area and requires lots of practical knowledge to get command of it.

Analytics Vidhya

Analytics Vidhya is a community of Analytics and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com

Smit Srivastava

Written by

IE MBA Graduate| Technical Program/Product Manager [Data Science, Web Development & DevOps]in the Ad-Tech domain| Writer at Analytics Vidhya| A knowledge seeker

Analytics Vidhya

Analytics Vidhya is a community of Analytics and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com