Decorator Pattern in JavaScript

This article is for someone who is looking for a quick check on the decorator pattern and what to evaluate if it can be added into the toolbox of the daily programming. If you are looking for the formal or professional explanation (e.g. one with definitions and details and examples for interview preps) then refer to this article.

Using the decorator pattern, you can extend the functionalities of existing functions. Consider the following example code.

function greet() {
    console.log('hello, world');
}

Now, we want to extend the functionalities of this greet function by logging before and after the function prints the "hello, world" text. Of course, you can do the following to solve this problem.

function greet() {
    console.log('Before: greet prints');
    console.log('hello, world');
    console.log('After: greet prints');
}

But, if that was the case/question then why someone asked you at the first place in the interview question! In such a scenario, you need to (over) clever and solve this problem in different ways. One way to do it is, by decorator pattern. How? Simple - wrapping the existing function by another new function e.g.

function greet() {
    console.log('hello, world');
}

function greetWithLogs() {
    console.log('Before: greet prints');
    greet();
    console.log('After: greet prints');
}

But, again this is not the pragmatic (extendable) way to do it! Then? Let's do it in hard way -

  1. Create a new function.
  2. The new function returns a function.
  3. Pass the existing function that you want to extend to the new function as an argument.

Step - 1 - Implementation.

function withLogs() {
    
}

Step - 2 - New function returns a function.

function withLogs() {
    return function() {

    }
}

Step - 3 - Pass the existing function that we want to extend.

function withLogs(fn) {
    return function() {
        console.log('Before: greet prints');
        fn();
        console.log('After: greet prints');
    }
}

The implementation is done. We are now ready to use it. Let's create a greetWithLogs() function by passing greet to withLogs() function.

const greetWithLogs = withLogs(greet);

Now, calling the greetWithLogs() returns the desired result! You might have a question like, what are the advantages of doing this? Instead of creating a new function and calling the greet() function in it? withLogs is not tied to greetWithLogs() function only. You can do withLogs() with other functions that fetch the data from the database or call a function that fetches the user data.

const findByManyWithLogs = withLogs(findByMany);

// OR

const getUserInfoWithLogs = withLogs(getUserInfo);

No comments:

Post a Comment