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,8 @@
package prototype;
// Our Prototype interface: any class that can clone itself implements this.
// The return type T allows each implementing class to return its own type,
// not the raw interface type, which makes the client code cleaner.
public interface Copyable<T> {
T copy();
}

View File

@@ -0,0 +1,46 @@
package prototype;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Document implements Copyable<Document> {
private String title; // String: immutable, safe to share on copy
private String content; // String: immutable, safe to share on copy
private List<String> tags; // List: mutable, MUST be deep-copied
private DocumentMetadata metadata; // Mutable object, MUST be deep-copied
public Document(String title, String content, List<String> tags, DocumentMetadata metadata) {
this.title = title;
this.content = content;
this.tags = new ArrayList<>(tags); // defensive copy on construction
this.metadata = metadata;
}
// Copy constructor: the preferred Prototype implementation in modern Java
public Document(Document source) {
this.title = source.title; // immutable: share
this.content = source.content; // immutable: share
this.tags = new ArrayList<>(source.tags); // mutable: new list
this.metadata = source.metadata.copy(); // mutable: deep copy via Copyable
}
@Override
public Document copy() {
return new Document(this); // delegates to copy constructor
}
// Getters and setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public List<String> getTags() { return Collections.unmodifiableList(tags); }
public void addTag(String tag) { tags.add(tag); }
public DocumentMetadata getMetadata() { return metadata; }
@Override public String toString() {
return String.format("Document{title='%s', tags=%s, %s}", title, tags, metadata);
}
}

View File

@@ -0,0 +1,39 @@
package prototype;
import java.time.LocalDate;
public class DocumentMetadata implements Copyable<DocumentMetadata> {
private String author;
private LocalDate createdDate; // LocalDate is immutable — safe to share
private String version;
public DocumentMetadata(String author, LocalDate createdDate, String version) {
this.author = author;
this.createdDate = createdDate; // safe: LocalDate is immutable
this.version = version;
}
// Copy constructor: creates a new instance with the same values
public DocumentMetadata(DocumentMetadata source) {
this.author = source.author; // String: immutable, safe to share
this.createdDate = source.createdDate; // LocalDate: immutable, safe to share
this.version = source.version;
}
@Override
public DocumentMetadata copy() {
return new DocumentMetadata(this); // delegates to copy constructor
}
public String getAuthor() { return author; }
public LocalDate getCreatedDate(){ return createdDate; }
public String getVersion() { return version; }
public void setVersion(String v) { this.version = v; }
public void setAuthor(String a) { this.author = a; }
@Override public String toString() {
return String.format("Metadata{author='%s', date=%s, version='%s'}",
author, createdDate, version);
}
}

View File

@@ -0,0 +1,21 @@
package prototype;
import java.util.HashMap;
import java.util.Map;
public class DocumentRegistry {
private final Map<String, Document> prototypes = new HashMap<>();
// Register a prototype under a name
public void register(String name, Document prototype) {
prototypes.put(name, prototype);
}
// Return a fresh copy of the named prototype
public Document get(String name) {
Document prototype = prototypes.get(name);
if (prototype == null) throw new IllegalArgumentException("No prototype: " + name);
return prototype.copy(); // always return a copy, never the prototype itself
}
}

View File

@@ -0,0 +1,47 @@
package prototype;
import java.time.LocalDate;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Create the original document (imagine this was loaded from a database)
DocumentMetadata metadata = new DocumentMetadata("Alice", LocalDate.of(2025, 1, 15), "1.0");
Document original = new Document(
"Q1 Report",
"Revenue increased by 12%...",
List.of("finance", "quarterly"),
metadata
);
System.out.println("Original: " + original);
// Clone the document and apply only the differences
Document draft = original.copy();
draft.setTitle("Q1 Report — DRAFT");
draft.addTag("draft");
draft.getMetadata().setAuthor("Bob"); // only the copy's metadata changes
draft.getMetadata().setVersion("1.0-draft");
System.out.println("Draft: " + draft);
System.out.println("Original: " + original); // unchanged — deep copy worked
// Verify independence
System.out.println("\nSame object? " + (original == draft)); // false
System.out.println("Same tags? " + (original.getTags() == draft.getTags())); // false
System.out.println("Same meta? " + (original.getMetadata() == draft.getMetadata())); // false
// Registry demo: register a named template once, then hand out independent copies
DocumentRegistry registry = new DocumentRegistry();
registry.register("q-report-template", new Document(
"Quarterly Report Template", "## Executive Summary\n...",
List.of("quarterly", "finance"), metadata));
Document myReport = registry.get("q-report-template"); // a fresh, independent copy
myReport.setTitle("Q2 2025 Report");
myReport.addTag("q2");
System.out.println("\nFrom registry: " + myReport);
}
}

View File

@@ -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/