In complex systems, constructors often do heavy work: reading files, parsing XML/JSON, or querying databases.
The Issue: Each new runs this slow logic again.
The Impact: The system slows down when it creates hundreds of similar objects (like email notifications).
2. Why Singleton Fails Here
The Before code does not use a Singleton. This is a what-if. A Singleton is one shared instance. The whole app uses that same object.
The Conflict: If we used a Singleton for WelcomeEmail, calling setContent() on it would change the content for the entire application.
The Lesson: Use Singleton when you want every part of the app to see the same data. Use Prototype when you want every part to start from the same template and change its own copy.
3. Tight Coupling
The client code is forced to use the new keyword with a concrete class (new WelcomeEmail()).
The Issue: If you only have the interface (EmailTemplate), you cannot create a new object without knowing its exact class.
The Prototype Solution: With Prototype, you ask an existing object to "clone itself". The client does not need to know its class.
1package DesignPatterns.CreationalPatterns.PrototypeDesignPattern.Before;23interface EmailTemplate {4 void setContent(String content);5 void send(String to);6}78class WelcomeEmail implements EmailTemplate {910 private String subject;11 private String content;1213 public WelcomeEmail() {14 // Imagine this constructor involves heavy operations:15 // Loading large HTML/CSS templates, fetching branding from DB, etc.16 this.subject = "Welcome to our platform";17 this.content =18 "Welcome to our platform. We are glad to have you on board.";19 }2021 @Override22 public void setContent(String content) {23 this.content = content;24 }2526 @Override27 public void send(String to) {28 System.out.println(29 "Sending email to: " +30 to +31 "\nSubject: " +32 subject +33 "\nContent: " +34 content +35 "\n"36 );37 }38}3940public class Main {4142 public static void main(String[] args) {43 // ISSUE 1: Inefficiency44 // Calling 'new' multiple times re-runs the expensive constructor logic every single time.45 WelcomeEmail welcomeEmailPlus = new WelcomeEmail();46 welcomeEmailPlus.setContent(47 "Welcome to our plus platform. We are glad to have you on board."48 );4950 WelcomeEmail welcomeEmailNonPlus = new WelcomeEmail();51 welcomeEmailNonPlus.setContent(52 "Welcome to our non-plus platform. We are glad to have you on board."53 );5455 /* * WHY WE CAN'T USE SINGLETON HERE:56 * Singleton pattern ensures only ONE instance exists globally.57 * If we made WelcomeEmail a Singleton:58 * 1. Changing 'content' for 'welcomeEmailPlus' would also change it for 'welcomeEmailNonPlus'.59 * 2. We cannot have two different versions (Plus vs. Non-Plus) at the same time.60 * 3. Singleton is for "Global State"; Prototype is for "Independent Copies".61 */6263 welcomeEmailPlus.send("premium_user@example.com");64 welcomeEmailNonPlus.send("free_user@example.com");65 }66}67