Search⌘ K
AI Features

Understanding the Decorator Pattern

Explore the Decorator Pattern to extend function behavior transparently in Node.js. Understand how to wrap existing logic with composable, reusable decorators for logging, timing, and more, keeping your code clean and maintainable without changes to core functions.

Why this pattern matters

We’ve all been there: we need to add logging, tracing, caching, auth checks—or all of the above—to an existing function. The logic is solid, but now it has to report metrics, log inputs, and check a token. Suddenly, what was a clean 5-line function turns into a bloated mess.

This problem only worsens in a large codebase. Cross-cutting concerns creep into core business logic. Every route handler starts with the same logging boilerplate. Every service has inline conditionals for permissions or caching. Changes ripple everywhere.

We want a way to wrap behavior—without rewriting the function itself. That’s what the decorator pattern gives us. It lets us wrap a function or method to extend its behavior transparently. And in Node.js, it maps perfectly to functional wrappers, higher-order functions, and even the merging @decorator syntax.

This is clean, composable extensibility—without modifying the core.

How the pattern works

At its core, the Decorator Pattern works as a wrapper around existing functionality. It takes a function, extends its behavior, and returns a new one that works the same but with added functionality.

The basic structure looks like this:

function decorate(originalFn) {
return function wrapped(...args) {
// do something before
const result = originalFn(...args);
// do something after
return result;
};
}

Decorators are pure composition. We stack them, ...