Add all 23 GoF design pattern implementations
This commit is contained in:
30
01-creational/abstract-factory/Application.java
Normal file
30
01-creational/abstract-factory/Application.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package abstractfactory;
|
||||
|
||||
public class Application {
|
||||
|
||||
// The client holds references to the Abstract Factory and Abstract Products.
|
||||
// It never imports LightButton, DarkButton, or any concrete class.
|
||||
private final UIFactory factory;
|
||||
private Button submitButton;
|
||||
private TextField usernameField;
|
||||
|
||||
public Application(UIFactory factory) {
|
||||
this.factory = factory; // theme is injected; client doesn't decide
|
||||
}
|
||||
|
||||
public void buildUI() {
|
||||
// Ask the factory — get consistent products from the same family
|
||||
submitButton = factory.createButton();
|
||||
usernameField = factory.createTextField();
|
||||
}
|
||||
|
||||
public void render() {
|
||||
System.out.println("Rendering login screen:");
|
||||
usernameField.render();
|
||||
submitButton.render();
|
||||
}
|
||||
|
||||
public void simulateSubmit() {
|
||||
submitButton.onClick();
|
||||
}
|
||||
}
|
||||
7
01-creational/abstract-factory/Button.java
Normal file
7
01-creational/abstract-factory/Button.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package abstractfactory;
|
||||
|
||||
// Every button, regardless of theme, must be able to render and handle clicks
|
||||
public interface Button {
|
||||
void render(); // draw on screen
|
||||
void onClick(); // respond to a click event
|
||||
}
|
||||
11
01-creational/abstract-factory/DarkButton.java
Normal file
11
01-creational/abstract-factory/DarkButton.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package abstractfactory;
|
||||
public class DarkButton implements Button {
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println("[Dark Button] Charcoal background, white text, no border");
|
||||
}
|
||||
@Override
|
||||
public void onClick() {
|
||||
System.out.println("[Dark Button] Bright highlight ripple effect");
|
||||
}
|
||||
}
|
||||
10
01-creational/abstract-factory/DarkTextField.java
Normal file
10
01-creational/abstract-factory/DarkTextField.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package abstractfactory;
|
||||
public class DarkTextField implements TextField {
|
||||
private String value = "";
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println("[Dark TextField] Dark gray background, light placeholder text");
|
||||
}
|
||||
@Override
|
||||
public String getValue() { return value; }
|
||||
}
|
||||
14
01-creational/abstract-factory/DarkThemeFactory.java
Normal file
14
01-creational/abstract-factory/DarkThemeFactory.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package abstractfactory;
|
||||
|
||||
public class DarkThemeFactory implements UIFactory {
|
||||
|
||||
@Override
|
||||
public Button createButton() {
|
||||
return new DarkButton(); // Only Dark products come from this factory
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextField createTextField() {
|
||||
return new DarkTextField();
|
||||
}
|
||||
}
|
||||
11
01-creational/abstract-factory/LightButton.java
Normal file
11
01-creational/abstract-factory/LightButton.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package abstractfactory;
|
||||
public class LightButton implements Button {
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println("[Light Button] White background, dark text, 1px gray border");
|
||||
}
|
||||
@Override
|
||||
public void onClick() {
|
||||
System.out.println("[Light Button] Subtle gray ripple effect");
|
||||
}
|
||||
}
|
||||
10
01-creational/abstract-factory/LightTextField.java
Normal file
10
01-creational/abstract-factory/LightTextField.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package abstractfactory;
|
||||
public class LightTextField implements TextField {
|
||||
private String value = "";
|
||||
@Override
|
||||
public void render() {
|
||||
System.out.println("[Light TextField] White background, dark placeholder text");
|
||||
}
|
||||
@Override
|
||||
public String getValue() { return value; }
|
||||
}
|
||||
14
01-creational/abstract-factory/LightThemeFactory.java
Normal file
14
01-creational/abstract-factory/LightThemeFactory.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package abstractfactory;
|
||||
|
||||
public class LightThemeFactory implements UIFactory {
|
||||
|
||||
@Override
|
||||
public Button createButton() {
|
||||
return new LightButton(); // Only Light products come from this factory
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextField createTextField() {
|
||||
return new LightTextField();
|
||||
}
|
||||
}
|
||||
16
01-creational/abstract-factory/Main.java
Normal file
16
01-creational/abstract-factory/Main.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package abstractfactory;
|
||||
|
||||
// Entry point: the ONLY place that knows the theme
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Production: read theme from config or OS preference
|
||||
String theme = System.getProperty("app.theme", "light");
|
||||
UIFactory factory = "dark".equals(theme) ? new DarkThemeFactory() : new LightThemeFactory();
|
||||
|
||||
Application app = new Application(factory);
|
||||
app.buildUI();
|
||||
app.render();
|
||||
app.simulateSubmit();
|
||||
}
|
||||
}
|
||||
33
01-creational/abstract-factory/README.md
Normal file
33
01-creational/abstract-factory/README.md
Normal file
@@ -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/
|
||||
7
01-creational/abstract-factory/TextField.java
Normal file
7
01-creational/abstract-factory/TextField.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package abstractfactory;
|
||||
|
||||
// Every text field must be able to render and return its value
|
||||
public interface TextField {
|
||||
void render();
|
||||
String getValue();
|
||||
}
|
||||
13
01-creational/abstract-factory/UIFactory.java
Normal file
13
01-creational/abstract-factory/UIFactory.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package abstractfactory;
|
||||
|
||||
public interface UIFactory {
|
||||
|
||||
// Factory method for buttons — returns the abstract type, not LightButton or DarkButton
|
||||
Button createButton();
|
||||
|
||||
// Factory method for text fields — same principle
|
||||
TextField createTextField();
|
||||
|
||||
// Adding a new product type (e.g., Checkbox) means adding a method here
|
||||
// AND implementing it in every Concrete Factory. This is the one cost of the pattern.
|
||||
}
|
||||
Reference in New Issue
Block a user