The refactored code implements the Prototype Pattern by using Java's Cloneable interface and a Registry. Now the objects create their own copies, instead of the client calling new. Cloneable is a Java marker interface (it has no methods) that lets super.clone() copy an object's fields. WelcomeEmail.clone() makes a shallow copy, which is enough here because its fields are Strings.
1. Key Improvements
Performance via Memory Cloning
The Benefit: Instead of re-running expensive constructor logic (DB fetches, template parsing), the system copies the object's state in memory.
The Result: Creating the 1,000th email is as fast as creating the 2nd.
Decoupling (Interface-Based Creation)
The Benefit: The client (Main) no longer needs to know the WelcomeEmail class.
The Result: You can add new email types (e.g., PasswordResetEmail) to the Registry without changing any of your business logic code.
Independent State (Anti-Singleton)
The Benefit: Unlike a Singleton, which shares one instance, Prototype gives each user their own object, and all start from the same "blueprint."
The Result: Modifying the content for "User A" has zero impact on "User B."
2. Structural Breakdown
Component
Responsibility
Prototype Interface (EmailTemplate)
Declares the clone() method and the methods every template must have.
Concrete Prototype (WelcomeEmail)
Implements the clone() method to return a copy of itself.
Registry (EmailTemplateRegistry)
Acts as a "warehouse" for master copies. It stores initialized prototypes and provides clones to the client.
Client (Main)
Requests a clone from the registry and configures the specific details needed.
1package DesignPatterns.CreationalPatterns.PrototypeDesignPattern.After;23import java.util.*;45/**6 * 1. PROTOTYPE INTERFACE7 * Extends Cloneable to tap into Java's native memory-copying capabilities.8 */9interface EmailTemplate extends Cloneable {10 // Returns a copy of itself. This is faster than 'new' because it11 // copies the object state directly in memory.12 EmailTemplate clone();13 void setContent(String content);14 void send(String to);15}1617/**18 * 2. CONCRETE PROTOTYPE19 * Implements the clone logic. This class knows how to copy itself.20 */21class WelcomeEmail implements EmailTemplate {2223 private String subject;24 private String content;2526 public WelcomeEmail() {27 // This heavy setup (DB calls, CSS loading) happens ONLY ONCE28 // when the initial prototype is created in the Registry.29 this.subject = "Welcome to TUF+";30 this.content = "Hi there! Thanks for joining us.";31 }3233 @Override34 public WelcomeEmail clone() {35 try {36 // super.clone() performs a "Shallow Copy".37 // For complex objects with nested lists, you'd perform a "Deep Copy" here.38 return (WelcomeEmail) super.clone();39 } catch (CloneNotSupportedException e) {40 throw new RuntimeException("Clone failed", e);41 }42 }4344 @Override45 public void setContent(String content) {46 this.content = content;47 }4849 @Override50 public void send(String to) {51 System.out.println(52 "Sending to " + to + ": [" + subject + "] " + content53 );54 }55}5657/**58 * 3. PROTOTYPE REGISTRY (Optional but Recommended)59 * Stores "Master Copies" of your objects. Instead of the client60 * knowing concrete classes, they just ask the Registry for a type.61 */62class EmailTemplateRegistry {6364 private static final Map<String, EmailTemplate> templates = new HashMap<>();6566 static {67 // Initialize the 'Master' objects once.68 templates.put("welcome", new WelcomeEmail());69 }7071 public static EmailTemplate getTemplate(String type) {72 // NEVER return the original from the map.73 // Always return a clone so the original stays 'pure'.74 return templates.get(type).clone();75 }76}7778class Main {7980 public static void main(String[] args) {81 // Client doesn't use 'new' or know about 'WelcomeEmail' class.82 // It simply clones a pre-configured template.83 EmailTemplate welcomeEmail1 = EmailTemplateRegistry.getTemplate(84 "welcome"85 );86 welcomeEmail1.setContent("Hi Alice, welcome to TUF Premium!");87 welcomeEmail1.send("alice@example.com");8889 EmailTemplate welcomeEmail2 = EmailTemplateRegistry.getTemplate(90 "welcome"91 );92 welcomeEmail2.setContent("Hi Bob, thanks for joining!");93 welcomeEmail2.send("bob@example.com");9495 /* * SUCCESS: alice@example.com and bob@example.com have independent96 * objects, but we avoided the expensive setup costs of 'new'.97 */98 }99}100