What Are Design Patterns?
A design pattern is a reusable, proven solution to a recurring design problem — not a finished piece of code you copy-paste, but a template for how to structure classes and objects to solve a specific kind of problem. The idea was popularized by the “Gang of Four” (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) in their 1994 book Design Patterns: Elements of Reusable Object-Oriented Software, which catalogued 23 patterns still taught and used today.
Patterns give developers a shared vocabulary. Saying “let’s use a Factory here” or “this should be a Decorator” communicates a whole design idea in a few words, instead of a long explanation. That’s often the real value: not the code itself, but the shared mental model it represents.
Why They Matter (and Where They Don’t)
Design patterns exist to solve real problems:
- Flexibility — swapping algorithms or implementations without rewriting client code (Strategy, Bridge)
- Decoupling — reducing dependencies between components so changes in one don’t ripple everywhere (Observer, Mediator, Facade)
- Reuse — avoiding duplicated logic for common problems (Template Method, Iterator)
- Maintainability — making intent explicit so the next developer (often you, six months later) understands the “why,” not just the “what”
But patterns are a means, not a goal. Applying a pattern where it isn’t needed adds indirection and complexity for no benefit — this is sometimes called “pattern fixation.” A good rule of thumb: let the pattern emerge from a real, recurring problem in your code, rather than forcing your code to fit a pattern you read about last week.
The Three Families
The Gang of Four organized patterns into three categories based on their purpose:
Creational patterns deal with object creation — hiding the logic of how objects are instantiated so the rest of the code depends only on interfaces, not concrete classes.
Structural patterns deal with how classes and objects are composed into larger structures — making sure that when parts change, the whole system doesn’t have to.
Behavioral patterns deal with communication and responsibility between objects — how they interact, delegate work, and stay loosely coupled while collaborating.
How This Fits with Java and Quarkus
Plain Java gives you the classic implementations — interfaces, abstract classes, composition — exactly as the Gang of Four described them. But modern frameworks like Quarkus, built on CDI (Contexts and Dependency Injection), implement several of these patterns for you, as first-class features:
| Pattern | Manual Java | Quarkus/CDI equivalent |
|---|---|---|
| Singleton | private static instance + lazy init | @ApplicationScoped bean |
| Factory Method | Abstract creator classes | @Produces methods |
| Decorator | Wrapper classes | @Decorator + @Delegate |
| Proxy | Manual wrapper implementing the interface | Client proxies, @CacheResult |
| Observer | Manual observer lists | CDI events, @Observes |
| Strategy | if/switch on type or manual interface swap | Instance<T> injection with qualifiers |
Recognizing the underlying pattern behind a framework annotation makes the framework far less “magic” — @Observes isn’t a mystery once you know it’s Observer, and @ApplicationScoped makes immediate sense once you know Singleton.
This Series
This introduction kicks off a series covering all 23 classic design patterns, each with its own post including a UML diagram (in Mermaid), a plain Java implementation, and — where it applies — how the same problem is solved idiomatically in Quarkus:
- Creational: Singleton, Factory Method, Abstract Factory, Builder, Prototype
- Structural: Adapter, Decorator, Proxy, Facade, Composite, Bridge, Flyweight
- Behavioral: Strategy, Observer, Command, Template Method, Iterator, State, Chain of Responsibility, Mediator, Memento, Visitor
Each post stands on its own, so feel free to jump straight to the pattern you’re curious about.

