Updated June 14, 2023
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 Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, popularly known as the Gang of Four (GoF) in the book “Design Patterns.”
Design Patterns are broadly classified into 3 categories which are as follows:
- Creational Design
- Structural Design
- Behavioral 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, some of the most important patterns you should know about will be discussed in detail, such as module, prototype, observer, and singleton design patterns.
A design pattern, when defined, includes many properties or components such as the pattern name, description, context outline, problem statement, solution, design, implementation, illustrations, examples, co-requisites, relations, known usage, and discussions.
Types of JavaScript Design Patterns
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. In JavaScript, you can quickly build modules that resemble classes by declaring private variables and functions and returning 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, you cannot access the dataToBeAssigned variable using its variable object contentChanger. However, you can access it using its method or function, namely functionToModifyHTMLContent. This leads to achieving encapsulation.
2. Prototype design pattern
When performance is the most crucial parameter to consider, we can use the prototype design pattern. In this pattern, we create clones of the required main original object. For example, a data-driven application involves many database operations and transactions, which can sometimes be time-consuming. So do not make other processes wait 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 as follows-
To implement prototyping, you need a constructor that instantiates an object in the first place. Additionally, you can use the prototype keyword to achieve the same effect. It helps in binding the methods and variables to the object. An example that 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 as 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
We often face a situation in our application where the change in one part affects and leads to 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 a model-view-controller (MVC) pattern, a change in the model or date results in a change in the view, meaning it displays the change. 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
The singleton pattern helps instantiate 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 the same single resource instance its 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:
This way, we can use design patterns in huge-scale applications, avoid coding mistakes, and follow best practices while developing the most optimized code. It is necessary to identify which design pattern will apply when it comes to coding. Considering all the parameters before adopting a design pattern solution scheme is necessary.
Recommended Articles
This is a guide to Javascript Design Pattern. Here we discuss the introduction to JavaScript Design Patterns, different design patterns, and the sample codes & outputs. You may also look at the following articles to learn more –