Design Patterns in Javascript

Design Patterns in Javascript

What is a design pattern?

A design pattern in general refers to a commonly accepted general solution to a wide range of commonly occurring problems. They are the best solutions known so far for specific types of problem scenarios. When these specific types of problems occur, the best way to deal with it is the application of that specific design pattern.

Design patterns help make our task easier by facilitating proper structuring of code which helps solve all the scenarios/test cases of that particular problem. Design patterns are not restricted to any language. They are a common practice which can be applied to wide range of languages mainly the language which supports object oriented paradigm. Though JavaScript is not a completely object oriented currently(It will be from ES6 onwards), it has powerful concepts like prototype inheritance and closures which help us in implementing design patterns effectively.

Let us take a look some design patterns and how we can implement it in design patterns in JavaScript:

Singleton Design Pattern:

Singleton, as the name suggests, refers to a single object or a single instance that can exist in the entire application. A Singleton design pattern helps in achieving this.  A Singleton design pattern creates a mechanism by which only one instance of a particular object can exist. The object is created when the first call is made and for subsequent calls the earlier generated object is returned. Singleton is very much useful in cases where you want only one instance of the object to be available.

Consider the following example:

In the above example, we have demonstrated the implementation of singleton design pattern. First time when you instantiate the singleton constructor, it creates a singleton object with the name property as ‘John’. On subsequent invocation, even by passing another parameter for name, the earlier instance with name ‘John’ is returned. This implies that only one object exists in the system and subsequent invocation leads to the earlier object to be returned.

Factory Design Pattern: 

Factory design patterns are very commonly used for creation of objects. You provide the required parameters to the factory pattern and it returns an object created using those parameters. Their main purpose is to generate different objects on request. This helps in better structuring of code since the entire logic of object creation would reside in the factory and any issues with it can be effectively pin pointed.

Let us take a look at the below example to understand better:

In the above example we have a factory function ‘animalFactory’ which performs the task of creating the animal objects(Dog/Cat) depending on the description type. When we call the factory function, we provide all the description properties for the creation of the object. The respective dog or cat object is created depending on the ‘type’ property that we provide to the animalFactory.

Decorator Design Pattern:

Decorator pattern allows you to order objects at run time. You can have a basic object and at run time you can customize it by adding things to it.

Take a look at the below example:

In the above example, we have a basic object of pizza to which we apply ExtraTopping and ExtraCheese objects at run time which eventually reflects in the final price of the pizza.

Observer Design Pattern:

Observer design pattern is based on the principle where you have an observable to which the observers can subscribe to. Any change in state of the observable will be broadcasted to all the observers who have subscribed to the observable. A real life example of this would be a blog subscription where you are the observer since you have subscribed to the blog and the blog service is the observable which will notify you if there are any new articles posted in the blog.

Take a look at the below example:

We have two observers which subscribe to the blogObservable. When a new article is published the blogObservable notifies the data to the observers which is then printed.

Module Design Pattern

This is a very widely used design pattern. This allows you to create modular code by grouping together the functionalities that are similar thereby making the code easy to read and maintain.

Take a look at the example below. I have created a module ‘myModule’ and made it a self executing function. Then I have returned an object containing a set of functions of the module which I want the module to expose. In the example below, the functions are ‘myFunction1’, ‘myFunction2’ and ‘myFunction3’.

 

Revealing Module Design Pattern

This design pattern is just an enhancement over the Module design pattern, to overcome the problems with the earlier. If you see the code of module design pattern you will find that the object that we are returning from the module function is not that easy to understand and read. It contains the function definitions which makes it hard to read. This would be even worse if the returned object grows in size, with larger number of functions each itself running into a number of lines of code. If this happens then it would kind of nullify the advantages of a modular approach. So what do we do then?

We modify the module pattern to a revealing module pattern. The way of coding is just the same with one enhancement. In the returned object, instead of writing the function definition, we just give a reference to a private function. This way the returned object will be more compact and would be ‘revealing’ the functionalities of the module while keeping the abstraction intact since the implementation details are in the private function.This way the code will be easier to maintain and read as compared to the module design pattern.

For a deep understanding on Javascript Design Patterns you can refer the following books which explain the concept in detail:

  1. Learning JavaScript Design Patterns
  2. Mastering JavaScript Design Patterns
  3. Pro JavaScript Design Patterns (Recipes: a Problem-Solution Ap)

I hope this post was useful. Do feel free to let me know if any issues in understanding this in the comments below.

Comments are closed.