Design Patterns, Explained Simply · Foundations: Thinking in Patterns

What a Design Pattern Is (and Isn't)

Patterns are named, reusable answers to design problems that keep coming back. Learn what one contains, the three families, and why the name matters as much as the code.

The problem

A checkout function has grown an if/else for every payment method: card, PayPal, bank transfer, a wallet. Each new method means editing the same function, retesting all the others, and resolving merge conflicts with whoever else touched it this week.

In review, a senior engineer writes: "Make each payment method a Strategy." If you know the pattern, that one word explains the whole change. If you don't, it is jargon.

Real-world analogy

Think of cooking techniques. "Braise it" is not a recipe for one dish. It is a proven technique you apply to beef, chickpeas or leeks, and every cook who hears the word knows the steps. A design pattern is a technique like that: a proven way to arrange code that you adapt to your problem, with a name everyone shares.

The idea

The book that named the classic patterns, Design Patterns by Gamma, Helm, Johnson and Vlissides (the "Gang of Four", 1994), describes each one with four parts:

  • Name: a word that lets a team talk about the design ("use an Adapter here").
  • Problem: the situation where it helps.
  • Solution: the roles (classes, interfaces, objects) and how they work together. It is a shape, not code to paste.
  • Consequences: what you gain and what it costs.

The 23 classic patterns come in three families:

Family Question it answers Examples
Creational How do I create objects flexibly? Factory Method, Builder, Singleton
Structural How do I fit objects together? Adapter, Decorator, Facade
Behavioral How do objects share work and talk? Strategy, Observer, Command

What a pattern is not:

  • Not a library. You don't install "Observer"; you arrange your own code that way.
  • Not a goal. Code with no patterns can be excellent. Patterns are tools for specific problems.
  • Not language-bound. Python, TypeScript, Java and PHP express the same pattern with different syntax, which is why every example in this course has four tabs.

The code

The checkout problem, before and after. The "after" version is the Strategy pattern: each payment method is a separate object with the same pay method, and checkout just looks one up. Pick your language tab; the output is identical in all four.

From a growing if/else to interchangeable objectsTry it yourself
# Before: every new payment method means editing this function
def pay_v1(method, cents):
    if method == "card":
        return f"card charged {cents}"
    elif method == "paypal":
        return f"paypal charged {cents}"
    raise ValueError(f"unknown method {method}")


# After: each method is its own object with the same shape
class Card:
    def pay(self, cents):
        return f"card charged {cents}"


class PayPal:
    def pay(self, cents):
        return f"paypal charged {cents}"


class Wallet:  # a new method is a new class; checkout() never changes
    def pay(self, cents):
        return f"wallet charged {cents}"


METHODS = {"card": Card(), "paypal": PayPal(), "wallet": Wallet()}


def checkout(method, cents):
    return METHODS[method].pay(cents)


print(pay_v1("card", 1200))
for name in ["card", "paypal", "wallet"]:
    print(checkout(name, 1200))

Output

card charged 1200
card charged 1200
paypal charged 1200
wallet charged 1200

Adding Wallet did not touch checkout. That is the whole point: the part that changes often (payment methods) is separated from the part that stays the same (checkout).

Common mistakes

  • Pattern hunting. Starting from "where can I use a Visitor?" instead of "what problem do I have?" produces complicated code for simple problems.
  • Copying the textbook diagram exactly. Patterns are shapes. In Python or TypeScript, a Strategy can be a plain function; you don't need an interface and three classes.
  • Treating names as decoration. Naming the pattern in a class (ShippingStrategy) or a comment helps the next reader. Naming it wrongly (calling a Facade an Adapter) misleads them.

Key points

  • A design pattern is a named, proven solution shape for a recurring design problem: name, problem, solution, consequences.
  • The classic 23 come in three families: creational, structural and behavioral.
  • Patterns are not libraries or goals. Use one when you recognise its problem.
  • The shared name is half the value: one word can explain a whole design in review.
  • Further reading: What's a design pattern? and the Gang of Four book.

Practice questions

What are the four essential parts of a design pattern, according to the Gang of Four?

Answer

Name, problem, solution and consequences. The name gives the team a shared word, the problem says when to apply it, the solution describes the roles and how they collaborate (a shape, not finished code), and the consequences list the trade-offs.

Name the three families of classic design patterns and give one example of each.

Answer

Creational (how objects are created: Factory Method, Builder, Singleton), structural (how objects are composed: Adapter, Decorator, Facade) and behavioral (how objects divide work and communicate: Strategy, Observer, Command).

Is it a good idea to add as many design patterns to a codebase as possible? Why or why not?

Answer

No. Each pattern adds indirection (more classes or interfaces), which costs readability. Use a pattern when you actually have the problem it solves, for example code that keeps changing in one place. Simple code without patterns is often the best design.

Why does this course show the same example in four languages?

Answer

Because a pattern is a design idea, not syntax. The roles stay the same while the language features change: Python and TypeScript can often use plain functions where Java uses an interface and a class. Seeing the four side by side shows what is the pattern and what is just syntax.

Open in the app to mark lessons complete, take notes and track your progress.