Skip to content

Design Pattern: Prototype (Creational)

Copy an existing object instead of building a new one

Builds on Cloneable and clone()

Stage 3advanced1 min read

1. High Creation Cost

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.

In this topic

Before code1 file

Before/Main.java67 linesGitHub
package DesignPatterns.CreationalPatterns.PrototypeDesignPattern.Before;interface EmailTemplate {    void setContent(String content);    void send(String to);}class WelcomeEmail implements EmailTemplate {    private String subject;    private String content;    public WelcomeEmail() {        // Imagine this constructor involves heavy operations:        // Loading large HTML/CSS templates, fetching branding from DB, etc.        this.subject = "Welcome to our platform";        this.content =            "Welcome to our platform. We are glad to have you on board.";    }    @Override    public void setContent(String content) {        this.content = content;    }    @Override    public void send(String to) {        System.out.println(            "Sending email to: " +                to +                "\nSubject: " +                subject +                "\nContent: " +                content +                "\n"        );    }}public class Main {    public static void main(String[] args) {        // ISSUE 1: Inefficiency        // Calling 'new' multiple times re-runs the expensive constructor logic every single time.        WelcomeEmail welcomeEmailPlus = new WelcomeEmail();        welcomeEmailPlus.setContent(            "Welcome to our plus platform. We are glad to have you on board."        );        WelcomeEmail welcomeEmailNonPlus = new WelcomeEmail();        welcomeEmailNonPlus.setContent(            "Welcome to our non-plus platform. We are glad to have you on board."        );        /* * WHY WE CAN'T USE SINGLETON HERE:         * Singleton pattern ensures only ONE instance exists globally.         * If we made WelcomeEmail a Singleton:         * 1. Changing 'content' for 'welcomeEmailPlus' would also change it for 'welcomeEmailNonPlus'.         * 2. We cannot have two different versions (Plus vs. Non-Plus) at the same time.         * 3. Singleton is for "Global State"; Prototype is for "Independent Copies".         */        welcomeEmailPlus.send("premium_user@example.com");        welcomeEmailNonPlus.send("free_user@example.com");    }}

Done with this topic?

How well do you know it?

PreviousDesign Pattern: Builder (Creational)