Files
design-patterns/README.md

18 KiB

GoF Design Patterns in Java

Complete runnable Java 25 implementations of all 23 Gang of Four design patterns. Each pattern has a dedicated article at ankurm.com with a UML diagram, step-by-step explanation, and console output.

Structure

design-patterns/
├── 01-creational/
│   ├── factory-method/
│   ├── abstract-factory/
│   ├── builder/
│   ├── prototype/
│   └── singleton/
├── 02-structural/
│   ├── adapter/
│   ├── bridge/
│   ├── composite/
│   ├── decorator/
│   ├── facade/
│   ├── flyweight/
│   └── proxy/
└── 03-behavioral/
    ├── chain-of-responsibility/
    ├── command/
    ├── interpreter/
    ├── iterator/
    ├── mediator/
    ├── memento/
    ├── observer/
    ├── state/
    ├── strategy/
    ├── template-method/
    └── visitor/

Prerequisites

  • Java 25+ (Eclipse Temurin recommended)
  • No build tool required — plain javac / java

Run any pattern

# Linux / macOS / Git Bash (Windows)
javac 03-behavioral/strategy/*.java -d out/strategy
java -cp out/strategy strategy.Main
REM Windows Command Prompt
javac 03-behavioral\strategy\*.java -d out\strategy
java -cp out\strategy strategy.Main

Articles

Pattern Category Article
Factory Method Creational https://ankurm.com/factory-method-design-pattern-java/
Abstract Factory Creational https://ankurm.com/abstract-factory-design-pattern-java/
Builder Creational https://ankurm.com/builder-design-pattern-java/
Prototype Creational https://ankurm.com/prototype-design-pattern-java/
Singleton Creational https://ankurm.com/singleton-design-pattern-java/
Adapter Structural https://ankurm.com/adapter-design-pattern-java/
Bridge Structural https://ankurm.com/bridge-design-pattern-java/
Composite Structural https://ankurm.com/composite-design-pattern-java/
Decorator Structural https://ankurm.com/decorator-design-pattern-java/
Facade Structural https://ankurm.com/facade-design-pattern-java/
Flyweight Structural https://ankurm.com/flyweight-design-pattern-java/
Proxy Structural https://ankurm.com/proxy-design-pattern-java/
Chain of Responsibility Behavioral https://ankurm.com/chain-of-responsibility-design-pattern-java/
Command Behavioral https://ankurm.com/command-design-pattern-java/
Interpreter Behavioral https://ankurm.com/interpreter-design-pattern-java/
Iterator Behavioral https://ankurm.com/iterator-design-pattern-java/
Mediator Behavioral https://ankurm.com/mediator-design-pattern-java/
Memento Behavioral https://ankurm.com/memento-design-pattern-java/
Observer Behavioral https://ankurm.com/observer-design-pattern-java/
State Behavioral https://ankurm.com/state-design-pattern-java/
Strategy Behavioral https://ankurm.com/strategy-design-pattern-java/
Template Method Behavioral https://ankurm.com/template-method-design-pattern-java/
Visitor Behavioral https://ankurm.com/visitor-design-pattern-java/

Post ↔ Code Mapping

Each article is split into multiple runnable parts. This section maps every post section to the exact file(s) in this repository, so you can jump straight from "what I just read" to "the file that implements it." Updated pattern-by-pattern as each article is verified against Java 25.

Factory Method (01-creational/factory-method/)

Post Section File(s)
The Problem: Object Creation Leaks Into Business Logic NotificationService.java (anti-pattern shown for contrast — not called by Main)
Part 1 — The Notification Interface Notification.java
Part 2 — The Concrete Notification Classes EmailNotification.java, SmsNotification.java, PushNotification.java
Part 3 — The NotificationSender Class NotificationSender.java
Part 4 — The Concrete Sender Subclasses EmailSender.java, SmsSender.java, PushSender.java
Part 5 — Running It: Client Code and Output Main.java
Adding a New Channel (Slack) SlackNotification.java, SlackSender.java

Run it:

javac 01-creational/factory-method/*.java -d out/factory-method
java -cp out/factory-method factorymethod.Main

Abstract Factory (01-creational/abstract-factory/)

Post Section File(s)
Part 1 — The Abstract Products: Button and TextField Button.java, TextField.java
Part 2 — The Concrete Products (Light family) LightButton.java, LightTextField.java
Part 2 — The Concrete Products (Dark family) DarkButton.java, DarkTextField.java
Part 3 — The Abstract Factory: UIFactory Interface UIFactory.java
Part 4 — The Concrete Factories LightThemeFactory.java, DarkThemeFactory.java
Part 5 — The Client: Application Application.java, Main.java

Run it:

javac 01-creational/abstract-factory/*.java -d out/abstract-factory
java -cp out/abstract-factory abstractfactory.Main
# or, for the dark theme family:
java -Dapp.theme=dark -cp out/abstract-factory abstractfactory.Main

Builder (01-creational/builder/)

Post Section File(s)
Part 1 — The Product: HttpRequest (Immutable) HttpRequest.java
Part 2 — The Director: Encapsulating Common Configurations HttpClientConfig.java
Part 3 — Using the Builder: Client Code Main.java

Note: the Lombok @Builder example and the JDK standard-library snippets (HttpRequest.newBuilder(), StringBuilder, ProcessBuilder) are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 01-creational/builder/*.java -d out/builder
java -cp out/builder builder.Main

Prototype (01-creational/prototype/)

Post Section File(s)
Part 1 — The Prototype Interface: Copyable Copyable.java
Part 2 — The Nested Object: DocumentMetadata DocumentMetadata.java
Part 3 — The Concrete Prototype: Document Document.java
Part 4 — The Prototype Registry: DocumentRegistry DocumentRegistry.java
Part 5 — Using the Prototype: Client Code Main.java

Note: the ShallowVsDeepDemo snippet (shallow vs. deep copy) and the Cloneable-based example are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 01-creational/prototype/*.java -d out/prototype
java -cp out/prototype prototype.Main

Singleton (01-creational/singleton/)

Post Section File(s)
Implementation 1 — Eager Initialization AppConfigEager.java
Implementation 2 — Naïve Lazy Initialization AppConfigNaiveLazy.java
Implementation 3 — Synchronized Method AppConfigSynchronized.java
Implementation 4 — Double-Checked Locking AppConfigDCL.java
Implementation 5 — Initialization-on-Demand Holder AppConfigHolder.java
Implementation 6 — Enum Singleton AppConfigEnum.java
Running All Six Implementations Together Main.java

Each implementation is renamed to its own class (e.g. AppConfigEager, AppConfigHolder) so all six can be compiled together in one package and compared directly. Main.java exercises all six in one run. The "Breaking via Reflection," "Breaking via Serialization," and Spring @Component snippets are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 01-creational/singleton/*.java -d out/singleton
java -cp out/singleton singleton.Main

Adapter (02-structural/adapter/)

Post Section File(s)
Step 1 — Define the Target Interface PaymentGateway.java
Step 2 — The Adaptee (What You're Wrapping) StripeClient.java
Step 3 — The Object Adapter StripePaymentAdapter.java
Step 4 — The Client (Knows Nothing About Stripe) OrderService.java
Putting It Together: The Main Demo Main.java
Object Adapter vs Class Adapter StripePaymentClassAdapter.java

Note: the InputStreamReader JDK-adapter snippet is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 02-structural/adapter/*.java -d out/adapter
java -cp out/adapter adapter.Main

Bridge (02-structural/bridge/)

Post Section File(s)
Step 1 — The Implementor Interface Device.java
Step 2 — Concrete Implementors (TV and Radio) TV.java, Radio.java
Step 3 — The Abstraction (RemoteControl) RemoteControl.java
Step 4 — Refined Abstraction (AdvancedRemote) AdvancedRemote.java
Wiring It Together: Main Demo Main.java

Note: the "Class Explosion Problem — Visualised" pseudocode and the JDBC/SLF4J snippets are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 02-structural/bridge/*.java -d out/bridge
java -cp out/bridge bridge.Main

Composite (02-structural/composite/)

Post Section File(s)
The Problem: Treating Leaves and Containers Uniformly illustrative only — not part of this repository's runnable example
Step 1 — The Component Interface FileSystemItem.java
Step 2 — The Leaf (File) File.java
Step 3 — The Composite (Directory) Directory.java
Building and Using the Tree Main.java

Run it:

javac 02-structural/composite/*.java -d out/composite
java -cp out/composite composite.Main

Decorator (02-structural/decorator/)

Post Section File(s)
Step 1 — Component Interface TextProcessor.java
Step 2 — Concrete Component PlainTextProcessor.java
Step 3 — Base Decorator TextDecorator.java
Step 4 — Concrete Decorators UpperCaseDecorator.java, TrimDecorator.java, ProfanityFilterDecorator.java
Stacking the Decorators — Order Matters Main.java

Note: the JDK InputStream/BufferedInputStream/GZIPInputStream snippet is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 02-structural/decorator/*.java -d out/decorator
java -cp out/decorator decorator.Main

Facade (02-structural/facade/)

Post Section File(s)
The Subsystem (Complex, But Unchanged) — VideoFile VideoFile.java
The Subsystem (Complex, But Unchanged) — Codec interface Codec.java
The Subsystem (Complex, But Unchanged) — Concrete Codecs MPEG4CompressionCodec.java, OggCompressionCodec.java
The Subsystem (Complex, But Unchanged) — CodecFactory CodecFactory.java
The Subsystem (Complex, But Unchanged) — BitrateReader BitrateReader.java
The Subsystem (Complex, But Unchanged) — AudioMixer AudioMixer.java
The Facade VideoConversionFacade.java
Client Code: One Line Main.java

Note: the SLF4J LoggerFactory, JDBC DriverManager, and Spring JdbcTemplate snippets under "Facade in the JDK and Real Frameworks" are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 02-structural/facade/*.java -d out/facade
java -cp out/facade facade.Main

Flyweight (02-structural/flyweight/)

Post Section File(s)
Step 1 — The Flyweight (TreeType) TreeType.java
Step 2 — The Factory (TreeFactory) TreeFactory.java
Step 3 — The Context (Tree) Tree.java
Putting the Forest Together Main.java

Note: the "Flyweight in the JDK: String Pool and Integer Cache" and "Measuring the Benefit" snippets are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 02-structural/flyweight/*.java -d out/flyweight
java -cp out/flyweight flyweight.Main

Proxy (02-structural/proxy/)

Post Section File(s)
The Subject Interface DatabaseConnection.java
The Real Subject RealDatabaseConnection.java
Virtual Proxy: Lazy Initialisation LazyConnectionProxy.java
Logging Proxy: Cross-Cutting Concerns LoggingProxy.java
Wiring It Together: Proxy Chaining Main.java

Note: the "Dynamic Proxy with java.lang.reflect.Proxy" snippet is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 02-structural/proxy/*.java -d out/proxy
java -cp out/proxy proxy.Main

Chain of Responsibility (03-behavioral/chain-of-responsibility/)

Post Section File(s)
The Problem: Rigid Routing Logic illustrative only — not part of this repository's runnable example
Implementation: Support Ticket Escalation — base handler SupportHandler.java
Implementation: Support Ticket Escalation — the ticket SupportTicket.java
Each concrete handler checks only its own responsibility — Level 1 & 2 Level1Support.java, Level2Support.java
Level3Support and CriticalIncidentTeam follow exactly the same shape Level3Support.java, CriticalIncidentTeam.java
The chain is assembled in one place Main.java

Run it:

javac 03-behavioral/chain-of-responsibility/*.java -d out/chain
java -cp out/chain chain.Main

Command (03-behavioral/command/)

Post Section File(s)
Step 1 — Command Interface Command.java
Step 2 — The Receiver (TextEditor) TextEditor.java
Step 3 — Concrete Commands InsertCommand.java, DeleteCommand.java
Step 4 — The Invoker (CommandHistory) CommandHistory.java
Demo Main.java

Run it:

javac 03-behavioral/command/*.java -d out/command
java -cp out/command command.Main

Iterator (03-behavioral/iterator/)

Post Section File(s)
Custom Iterator Implementation — the Iterator interface BookIterator.java
Custom Iterator Implementation — the element type Book.java
Custom Iterator Implementation — the Aggregate (BookShelf, ForwardIterator, DecadeIterator) BookShelf.java
Custom Iterator Implementation — wiring it together Main.java

Note: the "How Java's For-Each Loop Uses Iterator" snippet (Iterable<Book> example) is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 03-behavioral/iterator/*.java -d out/iterator
java -cp out/iterator iterator.Main

Mediator (03-behavioral/mediator/)

Post Section File(s)
Implementation: Chat Room — the Mediator interface ChatMediator.java
Implementation: Chat Room — the Colleague User.java
Implementation: Chat Room — the Concrete Mediator ChatRoom.java
Implementation: Chat Room — wiring it together Main.java

Note: the "Mediator in Practice: MVC and Spring Events" snippet (ApplicationEventPublisher/@EventListener example) is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 03-behavioral/mediator/*.java -d out/mediator
java -cp out/mediator mediator.Main

Memento (03-behavioral/memento/)

Post Section File(s)
The Memento: Immutable and Opaque EditorMemento.java
The Originator (Editor) Editor.java
The Caretaker (History) History.java
Wiring it together (Main demo) Main.java

Note: the "Serialization as Memento" snippet (ObjectOutputStream/ObjectInputStream example) is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 03-behavioral/memento/*.java -d out/memento
java -cp out/memento memento.Main

Observer (03-behavioral/observer/)

Post Section File(s)
Implementation: Stock Price Monitoring — the Observer interface StockObserver.java
Implementation: Stock Price Monitoring — the Subject StockMarket.java
Implementation: Stock Price Monitoring — AlertObserver AlertObserver.java
Implementation: Stock Price Monitoring — PortfolioObserver PortfolioObserver.java
Implementation: Stock Price Monitoring — wiring it together Main.java

Note: the "Push vs Pull Notification Models" pull-model snippet and the "Thread Safety" CopyOnWriteArrayList snippet are illustrative only — they are not part of this repository's runnable example.

Run it:

javac 03-behavioral/observer/*.java -d out/observer
java -cp out/observer observer.Main

State (03-behavioral/state/)

Post Section File(s)
With State: Traffic Light — the State interface TrafficLightState.java
With State: Traffic Light — the Context TrafficLight.java
With State: Traffic Light — RedState RedState.java
With State: Traffic Light — GreenState GreenState.java
With State: Traffic Light — YellowState YellowState.java
With State: Traffic Light — wiring it together Main.java

Note: the "Without State: The if-else Machine" snippet is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 03-behavioral/state/*.java -d out/state
java -cp out/state state.Main

Strategy (03-behavioral/strategy/)

Post Section File(s)
Implementation: Pluggable Sorting — the Strategy interface SortStrategy.java
Implementation: Pluggable Sorting — BubbleSort BubbleSort.java
Implementation: Pluggable Sorting — MergeSort MergeSort.java
Implementation: Pluggable Sorting — QuickSort QuickSort.java
Implementation: Pluggable Sorting — the Context (Sorter) Sorter.java
Implementation: Pluggable Sorting — wiring it together Main.java

Note: the "Strategy in Java 8+: Lambdas as Strategies" snippet is illustrative only — it is not part of this repository's runnable example.

Run it:

javac 03-behavioral/strategy/*.java -d out/strategy
java -cp out/strategy strategy.Main

Reference