Software Design

Why Design Patterns Matter—and Why Not to Trust Them Blindly

The question “Do we still need to study design patterns?” comes up regularly in developer communities.

5 min read
Cover image for Why Design Patterns Matter—and Why Not to Trust Them Blindly

The question “Do we still need to study design patterns?” comes up regularly in developer communities.

Some say, “Learn them no matter what—they’re fundamental,” while others say, “Modern languages make half of them unnecessary.” Both views have merit, which makes the issue even more confusing.

The short answer: design patterns are well worth learning. But once “applying a pattern” becomes the goal itself, it becomes a fast track to ruining your code.

This article examines, in order, why design patterns are useful and why you shouldn’t trust them blindly.


What Are Design Patterns?

A design pattern is, in short, a catalog of proven solutions to recurring design problems.

It began in 1994, when GoF (Gang of Four) documented 23 patterns in the book 『Design Patterns』. Names such as Singleton, Factory, Observer, and Strategy all came from it.

The key point is that these patterns weren’t invented at someone’s desk. They emerged by observing developers solve similar problems in similar ways across countless projects, then giving those solutions names and organizing them into a catalog.

That’s why the essence of design patterns is closer to “organized experience” than to “new technology.”


Why They Matter 1 — A Shared Team Vocabulary

The greatest practical value of design patterns lies not in code, but in communication.

Instead of explaining, “Keep only one instance of this class, make it globally accessible, and defer initialization until first access,” you can simply say, “Let’s use a Singleton.”

Consider how much information is packed into a single code-review comment such as, “Wouldn’t the Observer pattern work better here?” Pattern names are an extremely high-compression language.

Without this vocabulary, you read team discussions, technical documentation, and comments in open-source code more slowly. It’s also why technical interviews keep asking about design patterns.


Why They Matter 2 — A Key to Reading Frameworks

The frameworks we use every day are already bundles of design patterns.

  • iOS’s UITableViewDelegate uses the Delegate pattern
  • NotificationCenterand Combine’s publishers use the Observer pattern
  • SwiftUI’s View protocol composition is close to the Composite pattern
  • URLSession.shared is a Singleton

Once you know the patterns, you can look at an unfamiliar framework API and infer, “Ah, this must be that structure.” You don’t just read documentation faster—you can predict what isn’t documented.

Illustration of an iOS app screen assembled from Delegate, Observer, Singleton, Factory, and Strategy pattern blocks
Delegate, Observer, Singleton… the frameworks we use every day are already assembled from patterns

Why They Matter 3 — Reusing Proven Solutions

Solving a problem from scratch and starting from solutions refined over decades are two very different starting points.

For example, the Factory pattern has already addressed the problem of “object-creation logic being scattered everywhere and easily missed during changes,” while the Observer pattern has addressed the problem of “having to update multiple screens whenever state changes.”

Patterns document not only solutions but also their trade-offs. Side effects such as “Singletons make testing harder because they are global state” are part of the pattern too. It’s like having a map that marks the mines previous developers stepped on.


So Why Shouldn’t We Trust Them Blindly?

Up to this point, design patterns may seem万能. The problem often starts “right after” you learn them.

When You Have a Hammer, Everything Looks Like a Nail

After learning patterns, you may want to apply them everywhere. This is the well-known golden hammer trap.

You wrap code that reads one setting in an Abstract Factory, introduce Strategy for logic with two branches, and split work that needs one class into three interfaces and four implementations.

Patterns are tools for reducing complexity, but used where the problem isn’t complex enough, the pattern itself becomes new complexity. If someone seeing the code for the first time must jump across six files to find the actual logic, that isn’t design—it’s a maze.

As Languages Evolve, Patterns Disappear

GoF’s 23 patterns were organized around C++ and Smalltalk as they existed in 1994. Many of them have since been absorbed by language features.

// 1994-era: Strategy pattern — protocol + implementation classes
protocol SortStrategy {
    func sort(_ numbers: [Int]) -> [Int]
}
final class AscendingSort: SortStrategy {
    func sort(_ numbers: [Int]) -> [Int] { numbers.sorted(by: <) }
}

// Today Swift: a single closure achieves the same goal
let sorted = numbers.sorted(by: >)

In languages where functions can be passed like values, most Strategy and Command patterns fit in a single closure. Swift’s enum, value types, and default protocol implementations also solve at the syntax level problems that once required patterns.

Another way to view patterns is as “things people structured manually to compensate for what the language couldn’t yet do.” So if you memorize the pattern catalog as timeless truth, you end up solving problems the language already handles in ways from decades ago.

When the Pattern Becomes the Goal

The most dangerous warning sign is when design discussions start with “Which pattern should we use?” rather than “How should we solve this problem?”

A pattern is closer to a destination you reach while solving a problem than to a starting point. Refactoring literature commonly advises: don’t install patterns from the outset; refactor toward them when the code comes under pressure in that direction.

Flowchart for deciding whether to apply a design pattern—review problem recurrence and trade-offs, then choose simple maintenance or pattern-based refactoring
A pattern is not a starting point, but closer to a destination you reach when pressure builds

So How Should You Use Them?

In summary, the balance looks like this.

When learning, look at the problem before the solution. You need to remember “in what situations” each pattern emerged so you can avoid it when those conditions don’t apply. Half of studying patterns is learning “when not to use them.”

When applying them, start with the simplest code. When duplication appears three times, a real change request arrives, and the current structure becomes burdensome—that’s the time to refactor toward a pattern. Buying complexity today for future flexibility is usually a losing trade.

When reading, use them actively. Pattern knowledge is pure upside, with no side effects, when reading other people’s code, frameworks, or open source. The danger of blind faith appears “when using” patterns, not “when reading” them.


Summary

  • Design patterns are a catalog of proven solutions to recurring design problems—the product of observation, not invention.
  • Why they matter: a team’s shared vocabulary, a key to reading framework design, and proven solutions documented together with their trade-offs.
  • Why not to trust them blindly: applying them to simple problems makes the pattern itself complexity (the golden hammer); many patterns disappear as languages evolve; and when the pattern becomes the goal, design is turned upside down.
  • Practical rule: start with the problem and simple code, then refactor toward a pattern when pressure builds. Use patterns freely when reading.