Add all 23 GoF design pattern implementations (2026-06-13)
This commit is contained in:
53
02-structural/composite/Directory.java
Normal file
53
02-structural/composite/Directory.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package composite;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Composite — a directory that can hold both Files (leaves)
|
||||
* and other Directories (composites).
|
||||
*
|
||||
* getSize() is recursive: it asks each child for its size and sums them.
|
||||
* The caller doesn't care whether a child is a File or Directory —
|
||||
* both implement FileSystemItem and answer getSize().
|
||||
*
|
||||
* This is the power of Composite: uniform treatment of simple and complex.
|
||||
*/
|
||||
public class Directory implements FileSystemItem {
|
||||
|
||||
private final String name;
|
||||
private final List<FileSystemItem> children = new ArrayList<>();
|
||||
|
||||
public Directory(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Directory add(FileSystemItem item) {
|
||||
children.add(item);
|
||||
return this; // fluent API for easy nesting
|
||||
}
|
||||
|
||||
public void remove(FileSystemItem item) {
|
||||
children.remove(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() { return name; }
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
// Recursion: each child knows its own size.
|
||||
// Files return their bytes; directories sum their children.
|
||||
return children.stream()
|
||||
.mapToLong(FileSystemItem::getSize)
|
||||
.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String indent) {
|
||||
System.out.printf("%s[DIR] %s/ (%,d bytes total)%n", indent, name, getSize());
|
||||
for (FileSystemItem child : children) {
|
||||
child.print(indent + " "); // recurse with deeper indent
|
||||
}
|
||||
}
|
||||
}
|
||||
27
02-structural/composite/File.java
Normal file
27
02-structural/composite/File.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package composite;
|
||||
|
||||
/**
|
||||
* Leaf — a single file. It has no children.
|
||||
* getSize() returns its own size. print() shows its name.
|
||||
*
|
||||
* Notice: the File has no knowledge of directories or nesting.
|
||||
* It just knows its own name and size.
|
||||
*/
|
||||
public class File implements FileSystemItem {
|
||||
|
||||
private final String name;
|
||||
private final long size;
|
||||
|
||||
public File(String name, long sizeBytes) {
|
||||
this.name = name;
|
||||
this.size = sizeBytes;
|
||||
}
|
||||
|
||||
@Override public String getName() { return name; }
|
||||
@Override public long getSize() { return size; }
|
||||
|
||||
@Override
|
||||
public void print(String indent) {
|
||||
System.out.printf("%s[FILE] %s (%,d bytes)%n", indent, name, size);
|
||||
}
|
||||
}
|
||||
12
02-structural/composite/FileSystemItem.java
Normal file
12
02-structural/composite/FileSystemItem.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package composite;
|
||||
|
||||
/**
|
||||
* Component interface — the common contract for BOTH files (leaves)
|
||||
* and directories (composites). Clients work through this interface
|
||||
* and never need to know which they're dealing with.
|
||||
*/
|
||||
public interface FileSystemItem {
|
||||
String getName();
|
||||
long getSize(); // total size in bytes (recursive for directories)
|
||||
void print(String indent); // display the tree
|
||||
}
|
||||
58
02-structural/composite/Main.java
Normal file
58
02-structural/composite/Main.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package composite;
|
||||
|
||||
/**
|
||||
* Composite Design Pattern — Runnable Demo
|
||||
*
|
||||
* Builds a file system tree with nested directories and files.
|
||||
* Demonstrates that getSize() and print() work uniformly on
|
||||
* leaves (File) and composites (Directory) without any instanceof checks.
|
||||
*
|
||||
* Run: javac composite/*.java && java composite.Main
|
||||
* Article: https://ankurm.com/composite-design-pattern-java/
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== Composite Design Pattern Demo ===\n");
|
||||
|
||||
// Build a file system tree
|
||||
Directory root = new Directory("project");
|
||||
|
||||
Directory src = new Directory("src");
|
||||
Directory main = new Directory("main");
|
||||
main.add(new File("App.java", 4_200))
|
||||
.add(new File("Config.java", 1_800))
|
||||
.add(new File("Application.yml", 3_100));
|
||||
|
||||
Directory test = new Directory("test");
|
||||
test.add(new File("AppTest.java", 2_600))
|
||||
.add(new File("ConfigTest.java", 1_200));
|
||||
|
||||
src.add(main).add(test);
|
||||
|
||||
Directory resources = new Directory("resources");
|
||||
resources.add(new File("application.yml", 1_500))
|
||||
.add(new File("logback.xml", 900))
|
||||
.add(new File("banner.txt", 200));
|
||||
|
||||
root.add(src)
|
||||
.add(resources)
|
||||
.add(new File("pom.xml", 8_400))
|
||||
.add(new File("README.md", 2_100));
|
||||
|
||||
// Print entire tree — recursion happens automatically
|
||||
System.out.println("File system tree:");
|
||||
root.print("");
|
||||
|
||||
System.out.printf("%nTotal project size: %,d bytes%n", root.getSize());
|
||||
|
||||
// Client treats File and Directory identically
|
||||
System.out.println("\n-- Treating File and Directory uniformly --");
|
||||
FileSystemItem[] items = { new File("standalone.txt", 500), src };
|
||||
for (FileSystemItem item : items) {
|
||||
System.out.printf("%s -> size: %,d bytes%n", item.getName(), item.getSize());
|
||||
}
|
||||
|
||||
System.out.println("\n=== Demo complete ===");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user