Introduction to Javascript Design Patterns
Javascript is an object-oriented language. While coding for object-oriented languages, all the developers face common problems in optimizing the code. These recurring problems are discussed and optimal solutions for them are provided. This repetitive problem while designing the code was first observed and officially put forward in 1995 by four people namely Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides popularly known as Gang of Four (GoF) in the book named “Design Patterns”.
Design Patterns are broadly classified into 3 categories which are as follows:
- Creational Design
- Structural Design
- Behavioural Design Patterns.
This is further subcategorized into many design patterns like Creational Patterns like an abstract factory, builder, factory method, singleton, structural patterns like adapter, bridge, decorator, proxy and behavioral patterns like the chain of response, observer, iterator, etc. There are many and the count is still increasing. Out of all of them, some of the most important and patterns you should know about will be discussed in detail such as module, prototype, observer and singleton design patterns.
Every design pattern consists of many properties or components when it is defined like pattern name, description, context outline, problem statement, solution, design, implementation, illustrations, examples, co-requisites, relations, known usage, and discussions.
Types of JavaScript Design Pattern
Below are the types of design pattern
1. Module design pattern
Modules in javascript provide loose coupling and independent working of certain code. One of the most important features of object-oriented programming is classes that provide encapsulation or data hiding and eventually make our data in code more secure. Modules resemble classes in javascript and can be easily built by declaring private variables and functions and return objects.
Modules are function expressions that should be immediately invoked. Let’s see how this can be achieved with the help of a javascript example –
Code:
<!DOCTYPE html>
<html>
<body>
<h1>Module Design Pattern</h1>
<p id="fieldToBeChanged">Temporary String</p>
</body>
<script>
var contentChanger=(function()
{
var dataToBeAssigned ='Replace content with this string<br>'
var modifyHTMLContent = function()
{
var elementOfHTML = document.getElementById('fieldToBeChanged');
}
return {
functionToModifyHTMLContent: function() { modifyHTMLContent(); document.write(dataToBeAssigned);
}
};
})();
contentChanger.functionToModifyHTMLContent();
// Outputs: 'Replace content with this string'
document.write(contentChanger.dataToBeAssigned); // undefined
</script>
</html>
Output:
In the above example, the dataToBeAssigned variable is not accessible by using its variable object contentChanger but can be accessed by using its method or function namely functionToModifyHTMLContent. This leads to achieving encapsulation.
2. Prototype design pattern
In situations where performance is the most crucial parameter to be considered, we can use the prototype design pattern. In this pattern, we create the clones of the main original object which is required. For example, in the data-driven application, many database operations, and transactions are involved which can be time-consuming sometimes. So to not make other processes go waiting as they require the object involved in some data operation, we can prepare the clones and make them available for other waiting processes. This drastically improves the performance of the application. The UML diagram represents how these objects can be cloned. is as follows-
To implement prototyping, it is required to have a constructor that instantiates an object in the first place. Further, the prototype keyword can be used to achieve the same. It helps in binding the methods and variables to object. An example which demonstrates how this can be achieved is as follows –
Code:
<!DOCTYPE html>
<html>
<body>
<h1>Prototype design pattern</h1>
<p id="fieldToBeChanged">Temporary String</p>
<p id="fieldToBeChanged2">Temporary String</p>
</body>
<script>
var vehicles = function()
{
this.numberOfWheels = 4;
this.nameOfManufacturingCompany ='Mercedes'; this.modelName ='Benz 5000';
}
vehicles.prototype.accelerate = function()
{
document.getElementById('fieldToBeChanged').innerHTML = "Fast"; // Run the car and speedup
}
vehicles.prototype.applyBrakes = function()
{
document.getElementById('fieldToBeChanged2').innerHTML = "Slow";
// Stop the car and slowdown
}
vehicles.prototype.accelerate(); vehicles.prototype.applyBrakes();
</script>
</html>
Output:
Alternatively, as we are only sending an object in the form of a function we can define a prototype as a function and expose only the details we want in the following way to achieve encapsulation.
Code:
var vehicles = function()
{
this.numberOfWheels = 4;
this.nameOfManufacturingCompany = 'Mercedes'; this.modelName = 'Benz 5000';
}
vehicles.prototype = function() { var accelerate = function() {
// Run the car and speedup
};
var applyBrakes = function() {
// Apply Brakes and slowdown the car
};
return {
pushBrakePedal: applyBrakes, pushAcceleratePedal: accelerate
}
}();
3. Observer design
Many times, we face a situation in our application where the change in one part affects and leads to do changes in other parts of the application. Here, we can inform the other parts about the changes in one part of the application by raising an event or executing the watches. For example, in MVC pattern that is model-view-controller, change in model or date leads to change in view i.e. it’s displayed. We can achieve decoupling and reduce dependency. The following UML diagram helps us know how we can do this in javascript –
4. Singleton design pattern
Singleton pattern helps in the instantiation of the object only once by the client and many instances of the same object. The most simple and easy to understand example consists of resource sharing. Multiple machines in the network, suppose your lab can access and use the same resource like printer, scanner or fax machines, etc. All share here same single resource instance it’s users in the network. In javascript, this can be achieved in the following way –
Code:
<!DOCTYPE html>
<html>
<body>
<h1>Singleton design pattern</h1>
</body>
<script>
var singletonPatternDemo = (function ()
{
var singleInstance;
function init()
{
function exampleOfPrivateFunc()
{
document.write("This data is secured by making it private")
}
var privateEntity = "Im also private"; return
{
exampleOfPublicFunc: function () { console.log( "The public can see me!" );
},
publicVariable: "I am also public"
};
};
return {
// Create an instance during first time and return same instance after that
//when called
getsingleInstance: function ()
{
if ( !singleInstance ) { singleInstance = init();
}
return singleInstance;
}
};
})();
var firstInstance = singletonPatternDemo.getsingleInstance(); var secondInstance = singletonPatternDemo.getsingleInstance(); document.write( firstInstance === secondInstance ); // true
</script>
</html>
Output:
In this way, we can use design patterns in applications with huge scale and avoid mistakes while coding and follow best practices while developing the most optimized code. It is necessary to identify which design pattern will be applicable when it comes with coding. It is necessary to consider all the parameters before adopting a design pattern solution scheme.