Nine classic Gang-of-Four design patterns implemented in Java with realistic examples (payments, notifications, order checkout) rather than the usual Animal/Shape toy examples — plus a short explanation of why each pattern earns its complexity, not just what it does. Every pattern has unit tests.
| Pattern | Example used | Intent | When to reach for it |
|---|---|---|---|
| Singleton | AppConfig |
Ensure exactly one instance exists, with a single global access point | Shared resources where having two instances would be a bug — app config, a connection pool, a logger |
| Factory Method | NotificationFactory creating Email/SMS/Push notifications |
Let calling code create objects without knowing the concrete class | You have a family of related classes and don't want if/else chains scattered everywhere they're created |
| Builder | UserProfileBuilder |
Construct complex objects step by step, especially with many optional fields | An object has several optional parameters — avoids constructors with 6+ arguments |
| Pattern | Example used | Intent | When to reach for it |
|---|---|---|---|
| Adapter | LegacyPaymentAdapter wrapping a mismatched legacy API |
Convert one interface into another the client expects | Integrating a third-party library or legacy code whose API doesn't match your app's |
| Decorator | Notifier stacked with SMS/Slack decorators |
Add responsibilities to an object dynamically, without subclassing every combination | You need optional, combinable behavior (multiple notification channels, request middleware) |
| Facade | OrderFacade wrapping Inventory/Payment/Shipping |
Provide one simple entry point to a complex subsystem | A multi-step process (checkout, onboarding) that most callers just want to trigger, not orchestrate themselves |
| Pattern | Example used | Intent | When to reach for it |
|---|---|---|---|
| Strategy | ShoppingCart with swappable PaymentStrategy |
Make an algorithm's implementation swappable at runtime | Multiple ways to do the same thing (payment methods, sorting comparators, validation rules) |
| Observer | OrderSubject notifying Customer/Warehouse |
Notify multiple dependents automatically when one object's state changes | Event-driven behavior — UI updates, pub/sub, anything with "when X happens, tell everyone who cares" |
| Command | RemoteControl executing/undoing Light commands |
Encapsulate a request as an object, so it can be queued, logged, or undone | You need undo/redo, a queue of deferred actions, or to decouple "who requests an action" from "who performs it" |
src/main/java/com/lwandiso/patterns/
├── creational/
│ ├── singleton/
│ ├── factorymethod/
│ └── builder/
├── structural/
│ ├── adapter/
│ ├── decorator/
│ └── facade/
└── behavioral/
├── strategy/
├── observer/
└── command/
Each pattern's package is self-contained and can be read independently — you don't need to understand Observer to follow Strategy.
mvn testMost design pattern tutorials use Animal/Shape/Vehicle examples that make the pattern easy to see but hard to connect to real code you'd actually write. These use a small, semi-connected domain (payments, notifications, order checkout) closer to what shows up in real backend work — partly so the "why would I ever need this" question has an obvious answer.
MIT