You might have used these design patterns several times or might have observed them in the code or somewhere, but you didn't recognize them. Well, maybe this article will help you understand some of them and also apply them next time you see a similar problem that is solved by them.
What are design patterns?
Design patterns are nothing but proven and tested solutions to some commonly occurring problems in software design. These patterns provide a more optimized way of tackling these recurring problems rather than having to solve them from scratch.
Factory Pattern
Factory pattern is used to create new objects using factory functions. Factory functions are nothing but those functions which provide new objects without the use of new
keywords.
Factory functions are useful when we need to create multiple objects with the same properties.
Proxy Pattern
Proxy patterns are used to access and set properties on target objects but not directly, rather using a proxy. Proxy is nothing but representing someone else. So, a proxy object will represent our target object and we will interact with the proxy object rather than the target object. In JavaScript, we can make use of Proxy
method to create a proxy object from an existing object. The first argument of the Proxy method is the object for which we want to create a proxy and the second argument can be various handlers for the target object, but get
and set
methods are commonly used.
When we try to access any property it will go through the proxy object and the proxy object will in turn access the original object and then return the value. And if you notice, we have modified the get and set methods to return a well-formed sentence. So if we access the property shirt, it will give us Value for name property is Shirt
. Similarly, for setting the value it will show Changing value of price to 2500
. A proxy can be used to add validation.
Singleton Pattern
Singleton pattern can be used to limit the instance of an object to at most one. This instance can be shared throughout the application and therefore a great way to manage the state globally.
Let's see an example
In this example, we create only a single instance of our settings and share it throughout the app. To make sure we do not create multiple instances, we make use of instanceOf
to check if an instance already exists, and if so we throw an error.
Although it looks like a good way to save memory, the Singleton pattern is considered an anti-pattern in JavaScript and it is recommended to avoid it. This is mainly because having something globally ends up polluting the global state and it can lead to a lot of unexpected behaviour.
Strategy Pattern
This pattern is used to run different functions/tasks based on different inputs/choices.
For example, if we have a payment system, we would want users to select their preferred payment method and proceed with the calculations accordingly.
Let's see how can we achieve this using the Strategy pattern
function ProcessingFeesStrategy(){
this.paymentMethod="";
this.setPaymentMethod=function(paymentMethod){
this.paymentMethod = paymentMethod
};
this.calculate=function(){
return this.paymentMethod.calculate();
}
}
function CreditCardMethod(){
this.calculate= otherDetails =>{\
//other processing details can be added here
return 4.12;
}
}
function UPI(){
this.calculate = otherDetails =>{
return 0.2;
}
}
const startegy1 = new CreditCardMethod();
const strategy2 = new UPI()
const ProcessingFee = new ProcessingFeesStrategy();
ProcessingFee.setPaymentMethod(startegy1); //4.12
console.log(ProcessingFee.calculate());
ProcessingFee.setPaymentMethod(strategy2);
console.log(ProcessingFee.calculate()) //0.2
We can see how we set different strategies that can be utilized using the same Strategy object (ProcessingFeesStrategy)
. This can be helpful in various other cases like calculating shipping in carts or deciding which offers to apply based on customer selection.
Iterator Pattern
This is the most commonly used pattern in JavaScript. I am sure each one of us has used it frequently in our daily lives. This is as straightforward as it sounds, iterating over a collection of objects.
This helps us to iterate or loop over a collection in a certain manner and define a set of rules on how to traverse the array/objects.
function Iterator(item){
this.item = item;
this.index=0;
}
Iterator.prototype = {
hasNext:function(){
return this.index<this.item.length;
},
next:function(){
return this.item[this.index++]
}
}
const iterator = new Iterator([1,2,3,4,5]);
while(iterator.hasNext()){
console.log(iterator.next())
}
This pattern is helpful when we want to have different ways or methods of traversing or accessing our array elements.
That's it for now folks! Now, whenever you write JavaScript, I hope you can identify these patterns next time you write JavaScript and use them to make life easier for you!
I hope you enjoyed reading this! If so, please like and share it with fellow JavaScript devs to help them
Also, don't forget to leave your valuable comments in case you have any feedback or questions.
Thank you for reading!!