Quick Answer

A pattern is a named, reusable solution to a recurring design problem. The five worth knowing first are Singleton, Factory, Strategy, Observer and Decorator. Recognise them in code you read; do not go looking for places to insert them.

What they are, and the warning first

Patterns were catalogued because experienced developers kept arriving at the same shapes independently. Naming them made design discussions shorter — "use a strategy here" replaces five minutes of description.

The warning matters as much as the patterns. Someone who has just learned them tends to apply them everywhere, and the result is three interfaces and a factory wrapping what should have been one function. That is worse than the code it replaced, because indirection makes reading harder.

Patterns are a response to a problem you already have. If the problem has not appeared, applying the pattern adds cost with no benefit. "Which pattern should I use here?" is usually the wrong question; "what is hard to change in this code?" is the right one.

Singleton — one instance, globally

Ensures a class has exactly one instance with a global access point. Used for database connection pools, configuration and loggers.

class Config:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.settings = {}
        return cls._instance

a = Config()
b = Config()
print(a is b)   # True -- the same object

It is also the most criticised pattern, for good reasons. It is global mutable state under another name, it makes testing awkward because tests share the instance, and it hides dependencies — a class using a singleton does not declare it needs one.

In Python a module is already a singleton, so a module-level object usually achieves this with none of the ceremony. Know the pattern for interviews; reach for dependency injection instead in real code.

Factory and Strategy

Factory moves object creation behind a function, so callers do not name concrete classes:

def get_parser(filename):
    if filename.endswith(".csv"):  return CsvParser()
    if filename.endswith(".json"): return JsonParser()
    raise ValueError(f"unsupported file: {filename}")

parser = get_parser(name)
data = parser.parse(name)

Adding an XML parser means changing one function, not every call site. The problem it solves is a growing if chain about types scattered through the codebase.

Strategy makes an algorithm swappable at runtime:

def apply_discount(cart, strategy):
    return strategy(cart.total)

flat_50   = lambda total: total - 50
percent_10 = lambda total: total * 0.9

apply_discount(cart, percent_10)

The classic sign you need it is a function containing a large if/elif selecting between behaviours that each vary independently. In languages with first-class functions, Strategy is often just passing a function — no classes required, which is a good example of a pattern being simpler than its textbook form.

Observer and Decorator

Observer lets objects subscribe to events instead of being called directly:

class OrderService:
    def __init__(self):
        self.listeners = []

    def subscribe(self, fn):
        self.listeners.append(fn)

    def place_order(self, order):
        save(order)
        for fn in self.listeners:
            fn(order)

service.subscribe(send_email)
service.subscribe(update_inventory)

Without it, place_order calls email, inventory and analytics directly and must change every time a new consequence is added. With it, the order service knows nothing about them. Every event listener you have used in JavaScript is this pattern.

Decorator wraps behaviour around something without modifying it. Python has syntax for it:

def log_calls(fn):
    def wrapper(*args, **kwargs):
        print(f"calling {fn.__name__}")
        return fn(*args, **kwargs)
    return wrapper

@log_calls
def process(order): ...

Logging, caching, timing and authentication checks are all naturally decorators, because they are concerns that apply to many functions without belonging to any of them.

How to actually use this knowledge

Read code and name what you see. Express middleware is Chain of Responsibility. React hooks are closures over state. @app.route in Flask is a decorator. Recognising these makes unfamiliar codebases far easier to navigate, which is the main practical payoff.

In interviews you may be asked to name patterns or spot one in a snippet. A strong answer names the pattern and the problem it solves — "Strategy, because the discount rules vary independently and we do not want a growing conditional".

When writing code, let patterns emerge. Write the straightforward version first. When it becomes hard to change — the same conditional appearing in three files, a class needing edits for every new type — that is when the pattern has earned its place. See SOLID principles for the ideas underneath most of them.

Frequently Asked Questions

Do I need to memorise all 23 Gang of Four patterns? No. Know the handful you will actually meet and understand the problem each solves. Recognising patterns while reading code is far more useful than reciting a catalogue.
Why is Singleton considered an anti-pattern? It is global mutable state with a nicer name. It hides dependencies, makes testing harder because tests share the instance, and is frequently used where a plain module-level object or dependency injection would be better.
Are design patterns language-specific? The problems are universal; the implementations vary considerably. Several patterns that require classes in Java are a single function in Python or JavaScript, because those languages have first-class functions.
When should I introduce a pattern? When the problem it solves has actually appeared — repeated conditionals about type, a class that must change for every new variant, or code that is hard to test. Applying patterns pre-emptively adds indirection for no benefit.
Are design patterns asked in interviews? Sometimes by name, more often as a design question where a pattern is the natural answer. Explaining the problem and trade-off matters more than reciting the textbook definition.