Add all 23 GoF design pattern implementations (2026-06-13)

This commit is contained in:
Ankur
2026-06-13 21:44:56 +05:30
commit a5beb61425
106 changed files with 2977 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 @@
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);
}
}