JavaScript and Gentlemen: Why You Need Design Patterns (and How They'll Simplify Your Life)

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

JavaScript and Gentlemen: Why You Need Design Patterns (and How They'll Simplify Your Life)

\n\n

Have you ever opened your old JavaScript project and thought: "Who wrote this? This is spaghetti code!"? If so — welcome to the club. Sooner or later, every developer faces a situation where code turns into chaos. And that's where design patterns in JavaScript come to the rescue — proven recipes for typical tasks.

\n\n

But let's agree right away: patterns are not a silver bullet. They are not magic that will make your code perfect overnight. They are tools. And any tool is only good when you know when and why to use it. That's exactly what we'll talk about.

\n\n

What are design patterns in simple terms?

\n\n

Imagine you are an architect. You don't reinvent the wheel or the shape of a doorway every time. You use proven solutions: arches, columns, load-bearing walls. Design patterns in JS are the same "architectural blueprints," but for code.

\n\n

They solve three main problems:

\n
    \n
  • Reusability — no need to reinvent the wheel;
  • \n
  • Readability — another developer will immediately understand your logic;
  • \n
  • Scalability — code is easy to extend without risking breaking everything.
  • \n
\n\n

In this article, we'll cover four of the most popular patterns that are genuinely useful in daily work. No fluff — just code and practice.

\n\n

1. Singleton: When You Need Only One

\n\n

There are situations where an application must have exactly one instance of a class. For example:

\n
    \n
  • A global state store (like a Redux store);
  • \n
  • A logger for recording errors;
  • \n
  • A connection to a database or API.
  • \n
\n\n

The Singleton pattern guarantees that no matter how many times you try to create an object, you get the same one.

\n\n

Example: Visit Counter

\n\n
class Counter {\n  constructor() {\n    if (Counter.instance) {\n      return Counter.instance;\n    }\n    this.count = 0;\n    Counter.instance = this;\n  }\n\n  increment() {\n    this.count++;\n  }\n\n  getCount() {\n    return this.count;\n  }\n}\n\n// Usage\nconst counter1 = new Counter();\nconst counter2 = new Counter();\n\ncounter1.increment();\ncounter1.increment();\n\nconsole.log(counter2.getCount()); // 2 — because it's the same object\nconsole.log(counter1 === counter2); // true\n
\n\n

When to use: when you critically need a single point of access to a resource. But be careful — a common side effect of Singleton in JS is global state, which is hard to test. Don't overuse it.

\n\n

2. Module: Encapsulation Done Smartly

\n\n

Before the arrival of ES6 Modules, developers used the Module pattern to create private and public methods. Even now, with import/export available, this approach remains useful for organizing logic within a single file.

\n\n

The secret lies in closures. We create a function that returns an object with methods, while internal variables remain inaccessible from the outside.

\n\n

Example: Shopping Cart

\n\n
const ShoppingCart = (function() {\n  // Private variables\n  let items = [];\n  \n  // Private method\n  function calculateTotal() {\n    return items.reduce((sum, item) => sum + item.price * item.quantity, 0);\n  }\n\n  // Public API\n  return {\n    addItem(product) {\n      const existing = items.find(item => item.id === product.id);\n      if (existing) {\n        existing.quantity++;\n      } else {\n        items.push({ ...product, quantity: 1 });\n      }\n    },\n    removeItem(productId) {\n      items = items.filter(item => item.id !== productId);\n    },\n    getTotal() {\n      return calculateTotal();\n    },\n    clear() {\n      items = [];\n    }\n  };\n}                

Blogs

Book Recommendations