diff --git a/01-creational/abstract-factory/README.md b/01-creational/abstract-factory/README.md new file mode 100644 index 0000000..ae42c20 --- /dev/null +++ b/01-creational/abstract-factory/README.md @@ -0,0 +1,33 @@ +# Abstract Factory Design Pattern — Java Example + +**Pattern:** Creational → Abstract Factory +**Article:** https://ankurm.com/abstract-factory-design-pattern-java/ + +## What this example shows + +A UI toolkit that produces families of related widgets — light theme or dark theme — without the client ever naming a concrete class. `Button` and `TextField` are abstract products; `LightButton`/`LightTextField` and `DarkButton`/`DarkTextField` are the two concrete product families. `UIFactory` declares the creation methods for the whole family; `LightThemeFactory` and `DarkThemeFactory` each produce one consistent family. `Application` is the client — it only depends on `UIFactory` and the abstract products, so swapping the entire theme is a one-line change. `Main` selects the factory via a system property. + +## How to run + +```bash +javac 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 +``` + +Requires Java 25. + +## Post Section ↔ File Mapping + +| 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` | + +Article: https://ankurm.com/abstract-factory-design-pattern-java/ +All patterns: https://ankurm.com/design-patterns-java/ diff --git a/01-creational/builder/README.md b/01-creational/builder/README.md new file mode 100644 index 0000000..8009463 --- /dev/null +++ b/01-creational/builder/README.md @@ -0,0 +1,30 @@ +# Builder Design Pattern — Java Example + +**Pattern:** Creational → Builder +**Article:** https://ankurm.com/builder-design-pattern-java/ + +## What this example shows + +An immutable `HttpRequest` assembled step by step instead of through a constructor with a dozen optional parameters. `HttpRequest` is the product — built once, never mutated afterward. `HttpClientConfig` is a director-style helper that encapsulates common request configurations so callers don't repeat the same builder calls. `Main` wires it together and shows the fluent builder chain in action. + +## How to run + +```bash +javac builder/*.java -d out/builder +java -cp out/builder builder.Main +``` + +Requires Java 25. + +## Post Section ↔ File Mapping + +| 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. + +Article: https://ankurm.com/builder-design-pattern-java/ +All patterns: https://ankurm.com/design-patterns-java/ diff --git a/01-creational/factory-method/README.md b/01-creational/factory-method/README.md new file mode 100644 index 0000000..b5c17cd --- /dev/null +++ b/01-creational/factory-method/README.md @@ -0,0 +1,32 @@ +# Factory Method Design Pattern — Java Example + +**Pattern:** Creational → Factory Method +**Article:** https://ankurm.com/factory-method-design-pattern-java/ + +## What this example shows + +A notification system where the "send" logic decides which channel object to create, instead of the client doing it with a switch statement. `Notification` is the product interface; `EmailNotification`, `SmsNotification`, and `PushNotification` are concrete products. `NotificationSender` declares the factory method and a template `send()` step shared by every channel; `EmailSender`, `SmsSender`, and `PushSender` each override the factory method to produce their own notification type. `NotificationService` is shown separately as the anti-pattern this pattern replaces — it is not called by `Main`. `Main` demonstrates the cost of adding a new channel (Slack) by adding one new product and one new creator, with zero changes to existing classes. + +## How to run + +```bash +javac factory-method/*.java -d out/factory-method +java -cp out/factory-method factorymethod.Main +``` + +Requires Java 25. + +## Post Section ↔ File Mapping + +| 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` | + +Article: https://ankurm.com/factory-method-design-pattern-java/ +All patterns: https://ankurm.com/design-patterns-java/ diff --git a/01-creational/prototype/README.md b/01-creational/prototype/README.md new file mode 100644 index 0000000..2444646 --- /dev/null +++ b/01-creational/prototype/README.md @@ -0,0 +1,32 @@ +# Prototype Design Pattern — Java Example + +**Pattern:** Creational → Prototype +**Article:** https://ankurm.com/prototype-design-pattern-java/ + +## What this example shows + +Documents cloned from existing instances instead of rebuilt from scratch. `Copyable` declares the cloning contract. `DocumentMetadata` is a nested object that must be copied correctly for a clone to be truly independent of its source. `Document` is the concrete prototype, implementing a real (not shallow) copy. `DocumentRegistry` stores a set of ready-made prototypes that callers clone on demand instead of constructing from raw parameters. `Main` demonstrates cloning from the registry and confirms the clone and original don't share mutable state. + +## How to run + +```bash +javac prototype/*.java -d out/prototype +java -cp out/prototype prototype.Main +``` + +Requires Java 25. + +## Post Section ↔ File Mapping + +| 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. + +Article: https://ankurm.com/prototype-design-pattern-java/ +All patterns: https://ankurm.com/design-patterns-java/ diff --git a/01-creational/singleton/README.md b/01-creational/singleton/README.md new file mode 100644 index 0000000..409920f --- /dev/null +++ b/01-creational/singleton/README.md @@ -0,0 +1,34 @@ +# Singleton Design Pattern — Java Example + +**Pattern:** Creational → Singleton +**Article:** https://ankurm.com/singleton-design-pattern-java/ + +## What this example shows + +Six different ways to implement a singleton, compiled and run side by side so their tradeoffs are directly comparable. `AppConfigEager` initializes at class-load time. `AppConfigNaiveLazy` defers initialization but is not thread-safe. `AppConfigSynchronized` fixes thread-safety at the cost of locking on every call. `AppConfigDCL` uses double-checked locking to avoid that per-call lock. `AppConfigHolder` uses the initialization-on-demand holder idiom for lazy, thread-safe initialization with no locking at all. `AppConfigEnum` uses a single-element enum, which the JVM guarantees is a singleton even against reflection and serialization attacks. `Main` exercises all six in one run. + +## How to run + +```bash +javac singleton/*.java -d out/singleton +java -cp out/singleton singleton.Main +``` + +Requires Java 25. + +## Post Section ↔ File Mapping + +| 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. The "Breaking via Reflection," "Breaking via Serialization," and Spring `@Component` snippets are illustrative only — they are not part of this repository's runnable example. + +Article: https://ankurm.com/singleton-design-pattern-java/ +All patterns: https://ankurm.com/design-patterns-java/