Course contentsShow
← Node.js
Lesson 637 of 1,9807. Web Framework Architecture and MiddlewareFree lesson

The Decorator Pattern for Routes

Wrap route handlers with higher-order functions to encapsulate repetitive cross-cutting concerns.

The Decorator Pattern for Routes

In this lesson, you will learn how to wrap your route handlers in higher-order functions to cleanly apply cross-cutting concerns like logging, validation, or authentication without cluttering your core business logic.

Beyond Middleware

While we have explored middleware chains to process requests, sometimes you need a more surgical approach. Instead of running a piece of logic for every request on a route, you might want to "decorate" a specific handler. The Decorator Pattern allows you to wrap a function with another function, adding new behavior before or after the original logic executes.

Think of it like a gift wrapper: the inner function is your core logic (the gift), and the wrapper is the decorator (the bow and paper).

Implementation

A decorator is a higher-order function that takes a route handler and returns a new function. Here is how you might implement a simple logRequest decorator:

// The Decorator
const withLogging = (handler) => {
  return async (req, res) => {
    console.log(`Executing request to: ${req.url}`);
    return await handler(req, res);
  };
};

// The Original Handler
const getUserProfile = async (req, res) => {
  res.send({ id: 1, name: 'Node Learner' });
};

// Applying the Decorator
app.get('/profile', withLogging(getUserProfile));

By wrapping getUserProfile, we inject logging behavior without touching a single line of code inside the profile logic itself. This keeps your handler pure and focused strictly on its primary responsibility.

Why Use This?

This pattern is incredibly powerful for "cross-cutting concerns"—tasks that aren't part of the core feature but must happen regardless. Whether you are adding performance metrics, enforcing specific authorization checks, or logging input data, decorators allow you to maintain clean, modular, and reusable code. You avoid the "spaghetti middleware" trap by explicitly decorating only the routes that require specific cross-cutting logic.

Key Takeaway: The Decorator Pattern allows you to encapsulate repetitive logic into reusable wrappers, keeping your route handlers clean and focused on their specific business requirements.