1. Overview
The Prototype Pattern is a creational design pattern (a pattern about how objects get created). It clones existing objects instead of building them from scratch. It helps most when creating an object with the new keyword is slower than copying one that already exists in memory.
Formal Definition
"Prototype pattern creates duplicate objects while keeping performance in mind. It provides a mechanism to copy the original object to a new one without making the code dependent on their classes."
The Photocopy Analogy
Think of preparing ten offer letters. Instead of typing the same letter ten times, you write it once, photocopy it, and change just the name on each copy. The Prototype Pattern works the same way. You start with a base object (the prototype), make copies, and change only what differs.
2. Class Diagram
The diagram below shows three parts. The Prototype Interface (EmailTemplate) says every template can copy itself. The Concrete Prototype (WelcomeEmail) knows how to copy itself. The Registry (EmailTemplateRegistry) keeps the master copies.
3. Deep Cloning vs. Shallow Cloning
In Java, the way you copy an object decides whether you get bugs. There are two kinds of copy:
- Shallow Cloning: Copies the object's own fields as they are. If a field holds a reference to another object (like a
List), the original and the clone both point to the same list. - Deep Cloning: Copies the object and all the objects it references. This is generally preferred in the Prototype Pattern because a change to a clone (like adding a new attachment to an email) does not touch the original template.
The example code in this repo uses a shallow super.clone(). That is safe there because WelcomeEmail holds only Strings, which cannot change in place. Use a deep clone when a field is a mutable object such as a List.
4. Pros and Cons
| Pros | Cons |
|---|---|
| Faster Creation: Skips expensive initialization logic or database hits. | Complexity: A true deep copy is hard to write when an object holds many references. |
Reduced Subclassing: You don't need a PremiumWelcomeEmail class; you just clone a WelcomeEmail and change the content. | Circular References: If objects refer to each other in a loop, cloning can run forever or crash. |
| Runtime Configuration: Lets you create and change complex objects while the program runs, based on user state. | Maintenance: If you add or change a field, you must update clone(). |
5. Summary of Creational Patterns
You have now seen all the main creational patterns. Here is how they compare:
| Pattern | Primary Purpose | When to Use |
|---|---|---|
| Factory | Which class to create? | When you have one interface with many implementations (e.g., Logistics). |
| Abstract Factory | Which family of classes? | When you need related objects to work together (e.g., Region-based Payments). |
| Builder | How to build a complex object? | When an object has many optional parameters (e.g., BurgerMeal). |
| Prototype | How to copy an object? | When creation is expensive and you need many similar copies (e.g., Email Templates). |