Add all 23 GoF design pattern implementations

This commit is contained in:
2026-07-25 10:50:29 +05:30
commit f5688a6b32
164 changed files with 4371 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
package flyweight;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Flyweight Design Pattern — Runnable Demo
*
* Creates 1000 trees of only 3 species. Without Flyweight: 1000 TreeType
* objects. With Flyweight: 3 TreeType objects (one per species), shared.
*
* Run: javac flyweight/*.java && java flyweight.Main
* Article: https://ankurm.com/flyweight-design-pattern-java/
*/
public class Main {
public static void main(String[] args) {
System.out.println("=== Flyweight Design Pattern Demo ===\n");
List<Tree> forest = new ArrayList<>();
Random rnd = new Random(42);
String[][] treeSpecs = {
{"Oak", "dark-green", "rough-bark"},
{"Pine", "blue-green", "needle-texture"},
{"Birch","light-green","smooth-white-bark"}
};
System.out.println("Creating 1,000 trees (only 3 TreeType objects should be created):");
for (int i = 0; i < 1000; i++) {
String[] spec = treeSpecs[i % 3];
TreeType type = TreeFactory.getTreeType(spec[0], spec[1], spec[2]);
forest.add(new Tree(rnd.nextInt(800), rnd.nextInt(600), type));
}
System.out.println("\nForest created. Drawing first 5 trees:");
for (int i = 0; i < 5; i++) {
forest.get(i).draw();
}
System.out.println("\n--- Memory summary ---");
System.out.println("Trees in forest : " + forest.size());
System.out.println("Unique TreeType objects in pool: " + TreeFactory.getPoolSize());
System.out.println("Without Flyweight : 1,000 TreeType objects");
System.out.println("With Flyweight : " + TreeFactory.getPoolSize() + " TreeType objects shared");
System.out.println("\n=== Demo complete ===");
}
}

View File

@@ -0,0 +1,31 @@
# Flyweight Design Pattern — Java Example
**Pattern:** Structural → Flyweight
**Article:** https://ankurm.com/flyweight-design-pattern-java/
## What this example shows
A forest of 1,000 trees shares just 3 `TreeType` flyweight objects (one per species) instead of allocating a new heavy object per tree. `TreeType` holds the intrinsic (shared) state — name, color, texture. `Tree` holds only the extrinsic (unique) state — x/y position — plus a reference to its shared `TreeType`. `TreeFactory` is the pool manager: `Map.computeIfAbsent()` returns an existing flyweight or creates and caches one.
## How to run
```bash
javac flyweight/*.java -d out/flyweight
java -cp out/flyweight flyweight.Main
```
Requires Java 25.
## Post Section ↔ File Mapping
| 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.
Article: https://ankurm.com/flyweight-design-pattern-java/
All patterns: https://ankurm.com/design-patterns-java/

View File

@@ -0,0 +1,31 @@
package flyweight;
/**
* Context — stores the UNIQUE (extrinsic) state for each tree instance.
* This is NOT the flyweight itself; it's the lightweight object that
* holds position data and delegates rendering to a shared TreeType.
*
* 10,000 Tree objects × (x:4 bytes + y:4 bytes + reference:8 bytes) = ~160 KB
* vs.
* 10,000 Tree objects × (name + color + texture + x + y) = potentially MBs
*/
public class Tree {
// Extrinsic (unique) state — different per tree
private final int x;
private final int y;
// Reference to the SHARED flyweight
private final TreeType type;
public Tree(int x, int y, TreeType type) {
this.x = x;
this.y = y;
this.type = type;
}
public void draw() {
// Passes extrinsic state (position) into the shared flyweight
type.draw(x, y);
}
}

View File

@@ -0,0 +1,29 @@
package flyweight;
import java.util.HashMap;
import java.util.Map;
/**
* Flyweight Factory — the cache that ensures each unique TreeType
* is only created once, no matter how many trees use it.
*
* This is the piece that makes Flyweight work:
* it intercepts creation requests and returns an existing
* shared instance if one already exists.
*/
public class TreeFactory {
// The pool of shared flyweights
private static final Map<String, TreeType> treeTypes = new HashMap<>();
public static TreeType getTreeType(String name, String color, String texture) {
String key = name + "_" + color + "_" + texture;
// Only create a new TreeType if we haven't seen this combination before
return treeTypes.computeIfAbsent(key, k -> new TreeType(name, color, texture));
}
public static int getPoolSize() {
return treeTypes.size();
}
}

View File

@@ -0,0 +1,29 @@
package flyweight;
/**
* Flyweight — holds the SHARED (intrinsic) state.
* TreeType is shared between all trees of the same species.
*
* If you have 10,000 oak trees, there's ONE OakType object in memory.
* Each individual tree only stores its unique position (extrinsic state).
*/
public class TreeType {
// Intrinsic (shared) state — same for all trees of this species
private final String name;
private final String color;
private final String texture; // imagine a large texture bitmap here
public TreeType(String name, String color, String texture) {
this.name = name;
this.color = color;
this.texture = texture;
System.out.println(" [TreeType created: " + name + "]"); // see how few are created
}
// Extrinsic state (x, y) is passed IN at render time — NOT stored here
public void draw(int x, int y) {
System.out.printf(" Drawing %s tree [%s/%s] at (%d, %d)%n",
name, color, texture, x, y);
}
}