Start Learning
Javaneer
Back to stage
Stage 1·Design Patterns Applied

Patterns as Vocabulary

What a design pattern really is - a named, reusable solution to a recurring problem - the Gang of Four categories, and the pattern-fever trap of forcing them where they don't fit.

13 min readIntermediate
On this page

Design patterns have a bad reputation, and it's half-deserved. Used well, they're a shared vocabulary - saying "wrap it in an adapter" conveys a whole design in three words. Used badly, they're a checklist juniors apply to prove sophistication, burying simple code under factories and visitors nobody needed. This module teaches patterns the honest way: as fixes for real pains in the ledger codebase, and with equal attention to when not to reach for them.

What a pattern actually is

A design pattern is a named, reusable solution to a problem that recurs in object-oriented design. The canonical catalog is the 1994 "Gang of Four" (GoF) book, which documented 23 patterns working engineers kept reinventing. A pattern isn't code you copy - it's a shape you adapt:

  • a name (so teams can talk about it),
  • a problem it solves (the recurring situation),
  • a solution structure (the participating classes and how they collaborate),
  • and consequences (what it costs and buys).

You already met patterns in the SOLID module without the labels: replacing the fee if/else with FeePolicy implementations was the Strategy pattern; injecting a TransactionRepository was Dependency Inversion realized. Patterns are just the named, catalogued versions of designs good engineers converge on.

The three GoF families

The 23 patterns group into three categories by what they're about:

  • Creational - how objects get made: Factory Method, Abstract Factory, Builder, Singleton, Prototype. (Decouple code from concrete construction.)
  • Structural - how objects are composed into larger structures: Adapter, Facade, Decorator, Composite, Proxy, Bridge, Flyweight.
  • Behavioral - how objects interact and share responsibility: Strategy, Observer, Template Method, Command, State, Iterator, Visitor, and more.

This module covers the handful you'll use constantly - one or two from each family - because most real code needs maybe six patterns, not twenty-three.

Pattern fever: the anti-lesson

The single most important thing about patterns is knowing when not to use one. Pattern fever is applying a pattern because you learned it, not because the problem demands it:

  • A SingletonFactoryProxyBuilder for something a plain constructor would do.
  • An AbstractStrategyFactory when there's exactly one strategy and always will be.
  • A Visitor over a class hierarchy that has two types and never grows.

Every pattern adds indirection - more classes, more names, more hops to follow. That cost is only worth paying when the pattern solves a real, present problem: a proven axis of change, a genuine third-party mismatch, an actual subclass explosion. A pattern applied to an imagined problem is just complexity with a fancy name.

The pattern is the destination, not the starting point

Don't design by asking 'which pattern should I use here?' Design by solving the problem simply, and let patterns emerge when a simple solution strains against real change. The best pattern usage is often invisible - you refactored toward Strategy because a second fee type arrived, not because you planned a Strategy up front. Reaching for the catalog first is how you get enterprise fizzbuzz.

Cooking techniques, not a recipe to follow blindly

Patterns are like named cooking techniques - 'deglaze,' 'emulsify,' 'braise.' A chef saying 'braise it' conveys a whole method instantly (shared vocabulary), and knowing techniques means you're never stuck. But a novice who just learned to flambé and now flambés the salad is doing pattern fever: applying a technique to show off, not because the dish needs it. Great cooks reach for a technique when the ingredient calls for it - and often the right technique is 'just boil it.' The catalog serves the dish, never the reverse.

Pattern or plain code?

A teammate's PR introduces an AbstractTransactionValidatorFactoryProvider with three levels of interfaces to validate that a transaction amount is positive - something a single if (amount <= 0) throw ... currently does. They argue it's 'more extensible and follows patterns.' How do you evaluate this, and what would you ask before accepting or rejecting it?

What is a design pattern, and what's the key risk in using them?

Key takeaways

  • A design pattern is a named, reusable solution to a recurring design problem - a name, a problem, a solution structure, and consequences.
  • The Gang of Four cataloged 23 patterns in three families: creational (object creation), structural (composition), behavioral (interaction).
  • You already used patterns in SOLID: replacing fee if/else with FeePolicy was Strategy; injecting a repository realized Dependency Inversion.
  • Pattern fever - applying patterns to imagined problems - is the main risk; every pattern adds indirection that must be justified by real change.
  • Design by solving the problem simply and let patterns emerge when simplicity strains; reaching for the catalog first produces needless complexity.
Was this lesson helpful?
Edit this page on GitHub