patterns guru: the original Gang of Four catalog · all 23 patterns

Software patterns
resolve forces.

A field guide to the 1994 design patterns—translated into JavaScript, Python, Ruby, C, Rust, Java, Go, C#, and TypeScript, re-evaluated after three decades of language evolution.

.

23original GoF patterns
3families: creation, structure, behavior
9language translations per pattern

Patterns are an attempt to write down good things we build repeatedly.

Especially those things that are not immediately obvious: that is, not yet part of our current toolkit.

Patterns embody the repeatable, reasonable ways we meet our needs while avoiding problems -- in a general a way, where the specifics aren't as important as the overall idea.

The idea is not to "use lots of patterns".

It's to be aware of patterns, and whole pattern languages, so you can choose to use them, or not.

Pressures and forces
need to be identified

A pattern helps with recurring pressures.

If you can't name the pressures, using a pattern is less enlightening.

If language features already resolve these pressures, use them.

Programming languages are, in general, low-level pattern languages.

But we want to name old and new solutions, to old and new conflicts.

This helps us to better expand our individual, and shared, expression and reasoning about computing.

Before the catalog

A pattern is not code you copy.

It is a recurring relationship among a context, a problem, competing forces, and a solution abstraction that will take many concrete forms. That is why the same GoF pattern looks class-heavy in 1994 C++, function-heavy in JavaScript, trait-heavy in Rust, and like structs plus function pointers in C.

Important: the empirical literature does not justify the claim that adding a named pattern automatically improves software. Studies repeatedly find trade-offs, confounders, and mixed effects. The right judgment, of good fit between problem and structure, is what matters most —not whether a UML diagram resembles the GoF book.
The deeper inheritance

From Christopher Alexander to software — in small steps.

The software pattern movement did not borrow “pattern” to mean a decorative motif. Alexander’s architectural patterns describe recurring situations where several needs pull in different directions. The solution is a relationship that resolves those wicked pressures without prescribing one identical structure every time.

1
Notice a repeated situation.People repeatedly move between a room and a garden.
2
Name the forces.Short route vs. weather protection; privacy vs. visibility; structure vs. freedom of movement.
3
Find a relation that resolves them.Put the opening where movement actually wants to occur; make transition space generous enough to support stopping, seeing, and passing.
4
Adapt locally.The relation repeats; the exact dimensions, materials, orientation, and details do not.
5
Connect patterns.A doorway participates in rooms, paths, light, thresholds, privacy, and outdoor space. A software object likewise participates in a larger ecology of dependencies.
Tiny interactive analogy

Where should the gate go?

Watch use reveal a recurring relation; then reinforce it.

ROOM GARDEN
The gate is far from the line of movement. People must detour because the design ignored a recurring force.
The software translation: “Factory,” “Observer,” or “Strategy” should not be a shape imposed before experience. Each should be a compact name for a recurrent conflict you can actually point to. Beck and Cunningham’s 1987 work and the later Hillside community explicitly pursued this Alexander-inspired idea.
Thirty years later

What aged well—and what changed?

Influence: enormous

The vocabulary entered mainstream frameworks and libraries; Fowler called the book enormously influential and pointed specifically to Java/.NET libraries.

Quality: conditional

A systematic review of 50 primary studies and a mapping study of roughly 120 report conflicting results and substantial measurement/context problems.

Languages learned

Iterator, callbacks, closures, events, traits, sum types, pattern matching, modules, and generators absorb much of the old ceremony. The pressure remains; the implementation shrinks.

Therefore the ratings below are an editorial synthesis, not popularity statistics. “Core” means the underlying move remains broadly useful; “Native” means modern language/library features often embody it directly; “Contextual” means strong only when its specific forces exist; “Caution” means the classic implementation can create as many problems as it solves.

Native · language/library absorbed itCore · still broadly usefulCommon · frequent at boundariesContextual · strong when its forces really existNiche · specializedCaution · real idea, hazardous default
Orientation

The 23 at a glance.

Filter by family or survival status. Click any tile to jump to its full explanation.

The catalog

One pattern at a time.

Every pattern has four levels: a human situation, a software situation, the original GoF move, and its modern translation. The code selector changes every card so you can read the whole catalog in one language, or compare all nine on any pattern.

The meta-lesson

The same pressure, different language.

Dynamic languages

JavaScript, Python, and Ruby can often replace “one class per variation” with first-class functions, closures, duck typing, modules, generators, and runtime delegation. This was the thrust of Norvig’s famous critique: a pattern can be evidence of missing language support.

Java / C#

Modern Java and C# kept the object vocabulary but added lambdas, records, events/delegates, streams, pattern matching, and richer concurrency APIs. Classic class-heavy implementations can often be compressed without losing the design relation.

Rust

Traits can express Strategy/Bridge-like variation; enums plus exhaustive matching can replace some State/Visitor machinery; ownership and typestate can encode constraints the original book had to enforce dynamically.

C and Go

C reveals that these patterns were never fundamentally “about classes”: structs, opaque handles, function pointers, and explicit context are enough. Go likewise tends toward small interfaces and functions; its newer iterator protocol is a striking example of pattern pressure becoming standard language/library vocabulary.

No unexplained jargon

Glossary.

Hover any underlined technical term in the prose; the same definitions live here for scanning.

References

Sources and further reading.

The explainer deliberately mixes primary history, language documentation, practitioner interpretation, and empirical software-engineering research. Source links are external; the explainer itself has no runtime dependencies.

The original book — Addison-Wesley / InformITPublisher description of the 23-pattern catalog, authorship, date, and intended trade-offs.
Hillside Group — Design Patterns LibraryCurrent home of the software-pattern community; emphasizes shared vocabulary and reusable experience.
Hillside Group — HistoryDocuments the 1993 retreat and the explicit effort to connect Alexander's ideas with object-oriented software.
Beck & Cunningham (1987), Using Pattern Languages for Object-Oriented ProgramsEarly adaptation of Alexander's pattern-language idea to object-oriented UI design.
Hillside — Patterns / Alexander definitionConcise explanation of context, forces, and solution; links pattern practice to Alexander.
Martin Fowler — Gang of FourInfluence assessment and the observation that Java/.NET libraries became full of GoF patterns.
Peter Norvig — Design Patterns in Dynamic LanguagesClassic argument that language features can absorb or drastically simplify patterns.
Refactoring.Guru — catalogAccessible modern summaries of 22 of the classic patterns and the three categories.
Refactoring.Guru — Why Interpreter is omittedA contemporary catalog author's rationale for treating Interpreter as unusually niche.
Rust Book — implementing the State patternShows traditional State, then a more Rust-native type-state alternative and discusses trade-offs.
Rust Design PatternsModern language-specific pattern catalog emphasizing idioms and trade-offs.
Rust Design Patterns — VisitorModern treatment of Visitor over heterogeneous structures.
Python Patterns Guide — IteratorExplains how Python absorbs Iterator at the language protocol level.
Python Patterns Guide — Decorator PatternClarifies GoF Decorator vs Python's @decorator language feature.
MDN — JavaScript iteration protocolsShows Iterator as a first-class JavaScript protocol used by for...of and generators.
Oracle Java — IteratorIterator in the Java Collections Framework.
Oracle Java — IterableConnects Iterable directly to enhanced for syntax.
Oracle Java — Observable (deprecated)Important nuance: Java deprecated this particular Observer implementation and points to richer event/reactive alternatives.
Microsoft Learn — delegates vs eventsLanguage/platform mechanisms that absorb much Observer/Command/Strategy plumbing in C#.
Ruby EnumerableRuby's standard traversal abstraction; classes supply each and gain collection operations.
Ruby SingletonA standard-library implementation explicitly named for the GoF Singleton pattern.
Go blog — range over function typesGo 1.23 iterator functions: another example of a pattern becoming language/library protocol.
Wedyan & Abufakher (2020) — systematic literature reviewReviewed 50 primary studies; reports contradictory quality findings and strong confounding factors.
Ampatzoglou et al. (2012) — assessing impact on software qualityArgues pattern application is usually a trade-off: some quality attributes improve while others may weaken.
Ampatzoglou et al. (2013) — research mapping studyMapping of about 120 primary studies; highlights controversial quality results and uneven empirical coverage.

Compare languages