Skip to content

Repository files navigation

Java Design Patterns -- Bookshop Examples

Read this as a website:https://williajm.github.io/java_patterns/

Mainstream design patterns you'll actually meet in real Java codebases, each demonstrated with a small, self-contained bookshop example. No academic filler: only patterns that working Java developers both encounter constantly (in the JDK, Spring, and friends) and hand-write in ordinary application code.

Every pattern has:

  • a focused implementation under src/main/java/com/bookshop/<category>/<pattern>/
  • a README.md in the same package explaining the problem, the benefits, and where the pattern appears in the wild
  • a JUnit test written as executable documentation -- read the tests to see the pattern's payoff demonstrated, not just described

The patterns

CategoryPatternBookshop exampleKey benefit
CreationalBuilderAssembling an Order with optional gift message, promo code, express deliveryReadable construction of immutable objects; no telescoping constructors
CreationalSimple FactoryCreating card/PayPal/gift-card processors from a PaymentMethodCallers never couple to concrete classes; a new method is one compiler-checked change
CreationalSingletonShop-wide config and feature flags via the enum idiomGuaranteed single shared instance -- with an honest "prefer DI" caveat
StructuralAdapterWrapping a legacy pence-and-status-codes payment gateway behind a clean interfaceIncompatible APIs cooperate; the ugliness is quarantined in one class
StructuralDecoratorStacking gift wrap, express handling and greeting card onto an orderCombine extras at runtime without 2^n subclasses
StructuralFacadeOne checkout() call orchestrating inventory, payment and shippingThe correct sequence is written once; callers can't get it wrong
StructuralProxyA caching stand-in for the distributor's slow remote catalogCaching/laziness/access control added without touching callers
BehavioralStrategySwappable discount rules: loyalty, bulk, seasonal salePricing rules are configuration, not if/else ladders; each testable alone
BehavioralObserverEmail/SMS/dashboard reactions to restocksEvent source is decoupled from its ever-growing list of reactions
BehavioralTemplate MethodOne sales-report skeleton, CSV and HTML variantsThe algorithm exists once; formats can't drift apart
BehavioralChain of ResponsibilityOrder validation pipeline: stock -> address -> fraudChecks are independent components; the pipeline is just a list

Principles: SOLID + DRY

The same bookshop, applied to design principles rather than patterns. Each package shows the good design in code and the violation as a snippet in its README, with tests demonstrating the payoff.

PrincipleBookshop exampleKey benefit
Single ResponsibilityReceipt totals, printing and storage as three classesA receipt redesign can't break the maths
Open/ClosedNew shipping rates plug in; the quote calculator is never editedNew behaviour without re-risking tested code
Liskov SubstitutionA free sample chapter is not a Purchasable, so it can't reach the tillContract violations become compile errors, not incidents
Interface SegregationBookseller/StockManager/Accountant roles instead of one fat staff interfaceNo stubbed methods; till code can't call accounting
Dependency InversionOrderService depends on gateway/repository interfaces, details injectedBusiness logic tested with fakes; infrastructure swappable
DRYOne authoritative Vat class; receipt and invoice cannot disagreeA rule change is one edit; no silently-drifting copies

Anti-patterns, and using all this with judgement

Two docs that keep the rest of the repo honest:

  • Anti-patterns -- the five failure modes you'll actually meet (God Class, magic numbers, copy-paste, global mutable state, Golden Hammer), each with its counter-example in this repo.
  • Use with judgement -- none of these are rigid rules. Every pattern and principle here has a cost as well as a benefit, overuse is its own anti-pattern, and the page gives concrete signals for both over- and under-engineering.

Running

Requires JDK 17+ and Maven.

mvn verify # lints (Checkstyle) and runs every pattern's tests

What's deliberately left out -- and why

This is a curated list, not a complete catalogue: the bar for inclusion is "working Java developers hand-write this regularly". The rest of the Gang of Four is left out as a scope choice -- these patterns are real and still appear, just not often enough in ordinary application code to earn a chapter here:

  • Command -- when the need is simply "a task as an object", Runnable and lambdas usually carry it; the full pattern (queues, undo stacks, audit logs of operations) is genuinely useful but comparatively rare.
  • State -- real projects usually reach for an enum + switch or a state-machine library rather than the class-per-state shape.
  • Composite -- common inside UI/tree libraries, rarely hand-written in application code.
  • Iterator -- absorbed into the language: Iterable and for-each.
  • Abstract Factory, Prototype, Bridge, Flyweight, Visitor, Mediator, Memento, Interpreter -- each has its niche (a DI container does much of Abstract Factory's everyday job; Visitor still shines in compilers and AST tooling), but in typical application code they're rare enough that a focused list serves you better than a complete one.

If you're deciding whether to use a pattern at all: the tests here show the problem each pattern earns its keep on. No matching problem, no pattern -- the simplest code that works wins. The full argument, including the signals of over- and under-engineering, is in Use with judgement.

About

Commonly used Java patterns

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages