Prototype Pattern

What is the Prototype pattern?

Prototype means: make a new object by copying an existing one, instead of building it from scratch.

You keep one ready-made object around. When you need another like it, you clone it instead of repeating the setup work.

To build it you usually:

  1. Give the object a clone (or copy) method.
  2. Keep one configured instance around as the template.
  3. Copy mutable fields too, not just references, when it matters.

The problem it solves

Without cloning, every new object pays the full cost of construction, even when the result is nearly identical.

If building it reads a file, calls a service, or runs real validation, doing that twice — or a hundred times — is wasted work.

You want to say: build the expensive part once, then get cheap copies after that.


Basic cloning

Give the object a clone() method, keep one template around, and hand out copies instead of rebuilding.

The expensive setup message prints exactly once — when the template is built. Every clone after that is cheap.

Java’s Cloneable/clone() has a well-known reputation for being awkward — the checked exception, the cast. Many teams skip it entirely and write a plain copy method instead, which is exactly what the Python, Go, and TypeScript examples above already do.


Shallow vs deep copy

This is where most cloning bugs happen, so slow down here. A plain copy duplicates each field’s value. For simple fields (numbers, strings) that is fine. But for a field that points at something mutable, like a list, a shallow copy copies the reference — both objects end up pointing at the same list.

A deep copy fixes this by also copying the mutable field itself, not just the reference to it.

Rule of thumb: simple fields are fine to copy as-is; mutable fields — lists, maps, other cloneable objects — need to be copied themselves inside the clone.


Worked example: cloning a catalog listing

A more realistic case: a product listing with a mutable list of tags, used as a template for new listings.

Because clone() deep-copies tags, adding "custom" to the copy leaves the template untouched. A shallow copy here would have silently polluted the template too.


When it helps

Prototype earns its place when building an object from scratch is genuinely expensive — it hits disk, calls a service, or runs heavy validation — and you need several objects that start from the same state.

The test: would building this a second time do real, avoidable work that a copy would skip?


When it hurts

If constructing an object is already cheap, cloning adds complexity for no real savings. A shallow-copy bug can also sit undetected until two “independent” objects start mysteriously affecting each other.

Objects that reference each other in a cycle (A holds B, B holds A) make deep cloning tricky too — a naive deep copy can recurse forever.


Practical tips

  • Prefer a plain copy method or copy constructor over Cloneable/clone() for new code.
  • For every mutable field, ask: does this need its own copy inside clone()?
  • Say clearly whether a copy is shallow or deep — the next reader should not have to guess.
  • Reach for Prototype when construction cost, not construction complexity, is the problem. Expensive → Prototype. Complex but cheap → Builder.

Check your understanding

Prototype in one line?
Make a new object by copying an existing, ready-made one.

Shallow copy vs deep copy?
Shallow copy shares mutable fields with the original. Deep copy duplicates them too, so the two objects are fully independent.

Why do many languages skip built-in clone machinery?
It is easy to forget to deep-copy a mutable field. A plain copy method is clearer and just as effective.

When is Prototype worth using?
When building from scratch does real, repeatable work, and you need several similar objects.

What is the main risk?
Forgetting to deep-copy a mutable field, so the “independent” copy secretly shares state with the original.


What to learn next

Next: Adapter Pattern — the problem shifts from “how do I create objects” to “how do I make two incompatible interfaces work together.”