← Open in the full interactive course (progress tracking, search & more)

A design pattern isn't code you copy — it's a name experienced developers already agree on for a shape you'll recognize the moment you see it.

Picture two developers in a code review. The first one writes: "This class is directly constructing three different concrete logger implementations based on a config value, and every caller that needs a logger duplicates that same conditional. Could we pull that decision into one place, behind an interface, so callers just ask for 'a logger' without knowing which concrete class they're getting, and centralize the construction logic so adding a fourth logger type means changing one method instead of every call site?" The second developer writes: "Use a Factory here." Both comments describe the identical piece of feedback. One took four sentences; the other took three words.

That compression is the entire point of a design pattern. It's not a library you install, and it's not a C# language feature like async/await or pattern matching. It's a named, documented shape of solution — a recurring way of arranging classes and interfaces to solve a recurring problem — that enough developers already recognize that naming it communicates the whole idea instantly, without re-deriving it from scratch in every conversation.

In this lesson, you'll learn what a design pattern actually is, meet the three classic categories that organize the entire pattern catalog — Creational, Structural, and Behavioral — see how they map onto the specific patterns covered in this Part, and learn the honest, balanced caveat every experienced developer eventually learns: patterns solve specific, recurring problems, not everything, and reaching for one where it doesn't fit is its own well-known mistake.

What Is It?

The Simple Explanation

A design pattern is a reusable, named solution to a problem that keeps showing up, again and again, in object-oriented software — not a specific block of code you paste in, but a general shape: which classes exist, what they depend on, and how they talk to each other. When someone says "this is a Strategy" or "we need an Adapter here," they're pointing at that shape, and everyone who knows the name pictures the same structure immediately.

The Technical Definition

The term comes from a specific, famous source: Design Patterns: Elements of Reusable Object-Oriented Software (1994), written by four authors — Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides — universally nicknamed the "Gang of Four," or GoF. Their book catalogued 23 recurring solutions observed across real object-oriented systems, gave each one a name, and organized all 23 into three categories based on the kind of problem each one addresses. That vocabulary is still the industry standard three decades later — when a developer today says "GoF pattern," they mean one of these 23, or something clearly descended from them.

A pattern is not a library, and not a language feature

You can't using your way into a design pattern, and no NuGet package installs one for you. A pattern is a way of arranging code you write yourself — interfaces, classes, and the relationships between them — to solve a shape of problem that recurs across countless unrelated applications. Two completely different codebases, in different industries, with different business rules, can both contain a genuine Factory pattern — because "Factory" describes a structural shape, not a specific piece of business logic.

Why Does It Exist? — The Problem It Solves

PROBLEM → NEED → SOLUTION
PROBLEM
NEED
SOLUTION

This is worth being explicit about, because it's easy to misunderstand: the value of a design pattern isn't that it makes your code "more correct" by existing. Plenty of perfectly good code contains no named pattern at all. The value is communication — a shared shorthand that collapses a paragraph of design reasoning into a word, once both people already know what that word means.

Big Picture — the Three GoF Categories

The GoF organized all 23 patterns by asking one question of each: what kind of problem is this pattern actually about? Every pattern answers exactly one of three questions:

Creational

Structural

Behavioral

Question answered: "How do objects communicate and share responsibility?" — concerned with the assignment of responsibilities between objects and the patterns of communication between them: who calls whom, who's notified of what, and how an algorithm gets selected or coordinated at runtime.

Covered in this Part: Strategy (241), Observer (244), Mediator (246).

CategoryCore questionPatterns in this Part
CreationalHow do objects get created?Factory (240), Builder (245)
StructuralHow do objects fit together?Decorator (242), Adapter (243)
BehavioralHow do objects communicate?Strategy (241), Observer (244), Mediator (246)
Why only 7 of the 23? The GoF catalog has 23 named patterns; this Part deliberately covers the 7 most directly useful in everyday, modern .NET application code — the ones you'll genuinely reach for, or recognize other developers reaching for, in real ASP.NET Core and enterprise codebases. The other 16 (Singleton, Visitor, Chain of Responsibility, Prototype, and more) are real, valid, well-documented patterns — just outside this Part's scope. Knowing the category system means you'll be able to place any of them the moment you encounter one, even one not covered here.

How It Works — Recognizing a Pattern, Rather Than "Applying" One

HOW EXPERIENCED DEVELOPERS ACTUALLY USE PATTERN VOCABULARY
1. YOU HIT A RECOGNIZABLE SHAPE OF PROBLEM
2. YOU RECOGNIZE THE SHAPE, NOT JUST THE SYMPTOMS
3. YOU REACH FOR THE PATTERN'S KNOWN SHAPE — ADAPTED TO YOUR PROBLEM
4. YOU NAME IT — SO THE NEXT DEVELOPER RECOGNIZES IT TOO

Simple Example — the Same Design Decision, With and Without a Name

Without shared vocabulary

"So what I'm thinking is, instead of every place that needs to send a notification hard-coding which specific sender class it uses, what if we made an interface that all the senders implement, and then had one class whose whole job is picking the right one based on the user's preference, and everywhere else just depends on the interface instead of the concrete types..."

With shared vocabulary

"Let's put a Factory in front of the notification senders."

Meaning: Both sentences describe the exact same design. The second one only works because both people already know what "Factory" means — that's the entire value proposition of learning the catalog. It doesn't make the underlying design any better or worse; it makes talking about the design dramatically faster.

Real-World Example — a Code Review, Sped Up by Vocabulary

A pull request adds payment processing that supports Stripe, PayPal, and wire transfers, with a switch statement picking the right gateway in every controller that charges a customer. A reviewer, instead of writing several paragraphs of restructuring advice, leaves one comment: "This looks like it wants a Factory — pull the switch into one PaymentGatewayFactory.Create(method), and have every controller depend on IPaymentGateway instead." The author, having studied lesson 240, immediately knows exactly what shape of change is being requested — no meeting required, no diagram needed. That's the payoff this entire Part is building toward: every pattern lesson from here on is depositing one more entry into a vocabulary you and your teammates will use to move faster together.

Analogy — Musical Chord Names

"Play a G7 there" vs. describing every individual note

A guitarist could say "play G, then B, then D, then F, all at once, in this specific voicing" — or they could just say "play a G7." Both instructions produce the identical sound. The chord name doesn't create anything new; the notes existed and could be combined that way long before anyone named the combination. What the name buys you is speed of communication between musicians who already share the vocabulary — and the ability to recognize "oh, that's a G7" the instant you hear it, rather than puzzling out the individual notes from scratch every time.

Design patterns work exactly the same way. "Factory," "Adapter," "Observer" don't create new capabilities C# didn't already have — interfaces, constructors, and delegates already existed. The names just let developers who share the vocabulary recognize and discuss a familiar shape instantly, the way musicians recognize a chord by name instead of by note-by-note description.

Under the Hood — Where This Vocabulary Actually Comes From

THE DESIGN REASONING BEHIND THE CATALOG
1. PATTERNS DIDN'T INVENT NEW LANGUAGE FEATURES
2. MOST PATTERNS ARE, AT THEIR CORE, APPLIED SOLID DISCIPLINE
3. THE CATALOG WAS OBSERVED, NOT INVENTED FROM SCRATCH

Common Confusion

"Design pattern" vs. "algorithm"

An algorithm (like binary search, or quicksort) is a specific, step-by-step procedure for computing a result. A design pattern is not a procedure at all — it's a structural arrangement of classes and interfaces describing who depends on whom and who talks to whom. You could implement the exact same algorithm inside a Strategy pattern, a Factory Method, or plain unstructured code — the pattern is about the surrounding shape, not the computation inside it.

"Design pattern" vs. "architecture"

Patterns operate at the scale of a handful of classes solving one recurring, local problem. Architecture — covered later in this Part with Clean Architecture (249) and Hexagonal Architecture (250) — operates at the scale of an entire application's structure: which layers exist, and which direction dependencies are allowed to flow between them. A single architecture can, and usually does, contain dozens of individual design patterns inside it; they're related ideas at very different zoom levels, not the same thing.

"Using a named pattern" doesn't automatically mean "good code"

A Factory wrapped around a single implementation that will never have a second one isn't better code for being "a real GoF pattern" — it's unnecessary indirection wearing a familiar name. The pattern's presence isn't the goal; solving the actual recurring problem cleanly is the goal, and sometimes a pattern is the cleanest way to do that, and sometimes it very much isn't. The rest of this section addresses that directly.

Common Mistakes

Mistake 1 — "Pattern-itis": forcing a named pattern where direct code would be clearer

Wrapping a single, simple, unlikely-to-change piece of logic in a full Strategy interface with one concrete implementation, or building an Observer/event setup for a notification that will only ever have exactly one, fixed listener — reaching for a pattern's ceremony because it's a pattern, not because the actual problem calls for it.

Ask first: is this recurring problem actually present — multiple interchangeable implementations, a genuine need to decouple creation from use, several unrelated listeners? If the answer is no, plain, direct code is the correct choice, and it's not a lesser choice for being pattern-free.

Mistake 2 — Treating the catalog as a checklist to work through

Deciding a new feature "needs" a Factory, a Strategy, and an Observer because those are the patterns from the most recent lesson, rather than because the feature's actual shape calls for any of them.

Learn the catalog so you can recognize a shape when it genuinely appears — not so you can manufacture opportunities to use each name at least once in every project.

Mistake 3 — Using pattern names as a substitute for actually explaining the design

Saying "it's a Mediator" in a code review and stopping there, when the listener doesn't actually know the pattern well enough to picture the resulting structure — the name only compresses communication between two people who both already share the vocabulary.

Use the name as shorthand once you know it lands — and be ready to unpack it back into plain language for anyone still learning the catalog, exactly the way this Part is doing for you right now.

When Should I Use It?

And when it's overkill: almost always, at the moment you're tempted to add a pattern "for flexibility" without a concrete, present need driving it. Every pattern in this catalog adds a layer of indirection — an interface, an extra class, an extra level of delegation — and that cost is only worth paying when it's actually buying you something: real decoupling from a real, current source of change. "Pattern-itis" is a real, named anti-pattern precisely because unnecessary indirection has a genuine cost — code that's harder to read, harder to step through in a debugger, and harder for a new developer to follow — for no corresponding benefit.

Rule of thumb: a pattern earns its place when you can point at the specific problem it solves in your actual code today — not a hypothetical future problem. If you can't name the concrete pain the pattern removes, you likely don't need it yet.

Mental Model

A design pattern = a name for a shape of solution developers already recognize on sight.
Creational = how objects get made. Structural = how objects fit together. Behavioral = how objects communicate.

Remember:
· Patterns are vocabulary, not code you paste in — they compress a paragraph of design reasoning into a word.
· Every pattern in this Part builds on tools you already know: interfaces, composition, delegation, SOLID.
· "Pattern-itis" — forcing a named pattern where direct code is clearer — is a real, well-known mistake in its own right.

Key Takeaway


Check Your Understanding

You've met the GoF categories that will organize every remaining lesson in this Part. Let's confirm you can place a pattern correctly, and recognize when reaching for one is a mistake.

1. What is the most accurate description of a design pattern?

Show answer

Correct: B

Why B is correct: A design pattern is a named, documented structural shape — an arrangement of classes and interfaces — that recurs across unrelated codebases, built entirely from ordinary object-oriented tools already available in the language.

Why A is incorrect: A pattern isn't a fixed block of code to paste in — it's a shape you adapt to your own specific classes and problem.

Why C is incorrect: Patterns predate and are independent of any specific language's keywords — they're implemented using ordinary features a language already provides, not new syntax.

Why D is incorrect: No package installs a design pattern — patterns are a way of arranging code you write yourself.

Reinforcement: A pattern is a reusable shape and a shared name for it, not a piece of installable or copy-pasteable code.

2. Which GoF category does the Observer pattern (covered in lesson 244) belong to, and why?

Show answer

Correct: C

Why C is correct: Observer defines a one-to-many notification relationship between objects — precisely the "how do objects communicate" question that defines the Behavioral category.

Why A is incorrect: Observer doesn't concern itself with how Observer objects get constructed — that would be a Creational pattern's job. Observer is about notifying already-existing objects.

Why B is incorrect: Structural patterns are about composing objects into larger structures, not about the flow of notifications between independent objects — Observer's Subject and Observers aren't composed into a rigid structure at all.

Why D is incorrect: Every one of the 23 GoF patterns, Observer included, was explicitly assigned to one of the three categories in the original catalog.

Reinforcement: Ask "what kind of problem does this pattern solve?" — creation, composition, or communication — to place any pattern in its correct category.

3. A developer wraps a single, simple validation check — one that will never have a second implementation — inside a full Strategy interface with one concrete class, "because Strategy is a design pattern and design patterns are good practice." What does this lesson call this?

Show answer

Correct: B

Why B is correct: This is the exact scenario the lesson names "pattern-itis" — applying a pattern's structure because it's a recognized pattern, not because the concrete, recurring problem the pattern solves is actually present.

Why A is incorrect: SOLID principles guide toward flexibility where change is expected — they don't call for indirection around code that will never vary.

Why C is incorrect: Plain, direct code is just as testable as code wrapped in an unnecessary interface — testability isn't the justification here.

Why D is incorrect: The lesson explicitly warns against "just in case" pattern usage — future-proofing without a concrete present need is precisely the mistake being described, not a best practice.

Reinforcement: A pattern earns its place when its specific problem is genuinely present — not by default, and not as insurance against a hypothetical future.

4. Two developers, both familiar with the GoF catalog, are discussing a design. One says "let's put a Factory in front of this." Why does that short sentence work as effective communication?

Show answer

Correct: B

Why B is correct: The entire value of pattern vocabulary is that it lets people who share the same mental model communicate instantly — the name substitutes for a longer structural explanation precisely because both parties already know what that structure looks like.

Why A is incorrect: "Factory" isn't a language keyword at all — it's a name from a design catalog, unrelated to C# syntax.

Why C is incorrect: Naming a pattern doesn't write any code — a developer still has to design and implement the actual classes and interfaces.

Why D is incorrect: Word count has nothing to do with why the communication works — it's about a shared mental model, not brevity for its own sake.

Reinforcement: Pattern names function as shorthand only between people who already share the underlying vocabulary — that's the entire reason the catalog exists.

5. Which statement most accurately distinguishes a design pattern from an architecture like Clean Architecture (249)?

Show answer

Correct: A

Why A is correct: Patterns and architectures operate at very different zoom levels — a pattern solves one recurring, local design problem among a few classes, while an architecture like Clean Architecture governs the whole application's layer structure, and commonly contains many individual GoF patterns working inside it.

Why B is incorrect: The lesson explicitly distinguishes the two by scale — treating them as identical loses that important distinction.

Why C is incorrect: The Creational/Structural/Behavioral categories apply specifically to GoF design patterns, not to architectural styles, which aren't classified that way at all.

Why D is incorrect: Neither patterns nor architectures require any specific project structure by definition — that's an implementation detail, not the distinguishing factor between the two ideas.

Reinforcement: Zoom level is the key distinction: patterns are local and small-scale; architecture is global and whole-application-scale.

You now have the map for the rest of this Part's pattern catalog — Creational, Structural, Behavioral — and the vocabulary to recognize each pattern the moment it shows up in real code. Next up: Factory, the first Creational pattern.


dotnetmadeeasy.com — Learn C# and .NET, the right way.