Some Gang of Four patterns aged like good infrastructure; others aged like a workaround for a language limitation that no longer exists. Strategy, Observer, and Adapter still earn their place in a 2026 codebase because the problems they solve — swap an algorithm, notify subscribers, bridge two interfaces — never went away. Singleton, Template Method, and Abstract Factory mostly did not survive contact with modern language features and frameworks. This is the opinionated verdict, not another tour of all 23.
What changed in 2026
- The industry stopped treating the 1994 catalog as gospel. Recognizing the problem a pattern solves now matters more than naming the pattern correctly in a review.
- Language features quietly absorbed several patterns. First-class functions, generics, and exhaustive pattern matching do the job that Strategy, Abstract Factory, and Visitor used to need a class hierarchy for.
- Static analysis and AI-assisted review started flagging overused patterns automatically, catching a needless Singleton or an Abstract Factory with one implementation before a human reviewer has to.
- Framework-native versions won over hand-rolled ones. Observer inside a state library and Decorator inside a middleware chain are now the default; writing a bespoke version of either is a code-review smell, not a demonstration of skill.
The verdict, pattern by pattern
| Pattern |
Verdict |
Why |
| Strategy |
Survived, informally |
First-class functions made it a parameter, not a class hierarchy — the idea is more alive than ever |
| Observer |
Survived, everywhere |
Baked into state libraries, RxJS, and event emitters as core infrastructure, not an applied pattern |
| Adapter |
Survived |
Every SDK wrapper and API shim written today is an Adapter, named or not |
| Decorator |
Survived |
Middleware chains and Python-style decorators kept this one central and mostly implicit |
| Factory / Factory method |
Survived, smaller |
Still earns its keep exactly where creation logic genuinely branches; often just a function now, not a class |
| Repository |
Survived, expected |
Not Gang of Four originally, but now assumed practice for testable data access |
| Builder |
Adapted |
Still used for genuinely complex construction, but named-parameter objects replaced it for simpler cases |
| Command |
Adapted |
The object-with-an-execute-method version faded; the underlying idea survives as queued callbacks and undo stacks |
| Template Method |
Mostly retired |
A callback or a Strategy passed as a function does the same job without an inheritance hierarchy |
| Abstract Factory |
Mostly retired |
Rare outside GUI toolkits and plugin systems with real families of related objects |
| Singleton |
Actively harmful, still common |
Solves a real problem (one instance) with a mechanism (global mutable access) that consistently causes test and concurrency pain |
| Visitor |
Retired in typed languages |
Discriminated unions and exhaustive matching in TypeScript, Rust, and Kotlin do this more safely at compile time |
Why some survived and others did not
The patterns that held up all share one property: they solve a problem that has nothing to do with which language features happened to be missing in 1994. Notifying subscribers of a change, swapping an algorithm at runtime, and bridging two incompatible interfaces are permanent problems in software, so Observer, Strategy, and Adapter show up in every language era regardless of syntax. They also compose cleanly with modern features rather than fighting them — a Strategy is just a function reference in a language with first-class functions, no ceremony lost.
Template Method and Abstract Factory leaned on inheritance to solve problems that closures and generics now solve more directly — passing a function instead of overriding a protected method, or using generics instead of a hierarchy of parallel factories. Visitor existed largely to work around languages that could not exhaustively check a closed set of types at compile time; a discriminated union with a match or switch now does that job with a compiler error instead of a runtime dispatch table. Singleton is the odd one out: it did not get replaced by a language feature, it got replaced by better judgment. Dependency injection with a single-instance scope gives you the "exactly one" guarantee without the global mutable access that made Singletons a testing and concurrency liability.
Common mistakes
Learning all 23 patterns as if they carry equal weight in 2026. A handful do most of the daily work; the rest are worth recognizing, not memorizing. Start with Strategy and Observer.
Keeping a Singleton because "it has always been there," or writing a new one out of habit. If you are about to write a class whose only job is a getInstance() method, reach for dependency injection with a singleton scope instead.
Building an Abstract Factory for a single family of one, or an abstract base class purely so subclasses can override one method. Check whether a plain function parameter does the same job with less ceremony before adding the hierarchy.
Assuming a retired pattern is now wrong to use. Template Method still fits legitimate cases with real shared structure and per-step variation; retirement here means "usually replaced by something simpler," not "forbidden."
FAQ
Are design patterns outdated in 2026?
The catalog's exact class-based implementations are often outdated; the underlying problems they solve are not. Recognize the problem, then reach for whatever the current language's cleanest solution is.
Which pattern should I actually learn first?
Strategy and Observer. They appear constantly, map directly onto function references and event systems most developers already use, and unlock recognizing several other patterns as variations on the same idea.
Is Singleton ever the right choice?
Rarely, and usually a DI container's singleton scope achieves the same guarantee without a hardcoded global accessor, which is what actually causes the testing pain people blame on "the pattern."
Do functional languages need this list at all?
Less of it. Strategy, Command, and Template Method mostly dissolve into plain functions in a functional style. Structural patterns like Adapter and Decorator still apply regardless of paradigm.
Where to go next
For the fuller taxonomy this piece assumes you already know, see design patterns explained in 2026 and the factory pattern explained in 2026. For the principle several of these patterns exist to support, see inversion of control explained in 2026.