skip to content

What problem does the Prototype creational design pattern solve, and how does it produce new objects?

level: juniorimportance: must knowfreq 55%

answer

  1. Copy a configured exemplar, not a constructor call
  2. Expensive or fiddly instantiation
  3. clone() behind an abstract type
  4. Registry of exemplars = variants as data
  5. Real difficulty is shallow vs deep copy

basics

~20 s

Prototype creates a new object by copying an existing, already-configured object instead of building one from scratch. You ask the existing instance to clone itself. It helps when construction is slow or the setup is long and fiddly.

solid answer

~50 s

Prototype is a creational pattern whose intent is: create new objects by copying a prototypical instance rather than invoking a constructor and re-running the whole configuration. The prototype exposes a single operation — conventionally `clone()` or `copy()` — that returns a new object of the same concrete type with equivalent state. Callers hold the prototype through an abstract type, so they can duplicate an object without knowing its concrete class or its construction recipe. It pays off when instantiation is expensive (parsed configuration, precomputed tables, data loaded over the network) or configuration-heavy (dozens of setters/options that would otherwise be duplicated at every call site), and when the set of variants is decided at runtime — you register configured exemplars instead of writing a subclass or factory branch per variant. The hard part is not the pattern shape but copy semantics: deciding, field by field, what gets duplicated and what gets shared.

code

pseudocode · 14 lines
pseudocode
interface Shape { Shape clone(); void draw(); }

class Circle implements Shape {
  Point center; int radius; Style style;
  Shape clone() {
    // decide per field: duplicate or share
    return new Circle(center.copy(), radius, style); // style is immutable -> shared
  }
}

// client knows only the abstract type
Shape tool = palette.get("circle");   // a configured prototype
Shape placed = tool.clone();          // new object, no constructor knowledge
placed.moveTo(cursor);

go deeper

for a junior

State the intent — new objects by copying an existing configured one via clone() — and one motivating case such as expensive setup.

for a middle

Add the three roles plus the registry, contrast with Factory Method and Builder, and raise shallow vs deep copy as the real design decision.

for a senior

Discuss copy semantics field by field, aliasing bugs, cycles and shared references, non-copyable state (IDs, connections, listeners), and cost of deep copy versus rebuilding.

for a principal

Frame it as a decision about ownership and mutability: prefer immutability and sharing where possible; treat copy semantics as part of the type's contract, tested and documented, rather than an incidental method.

### The words first - **Creational pattern**: a reusable design solution concerned with *how objects get made*, so that the code needing an object is decoupled from the details of making it. Prototype, Factory Method, Abstract Factory, Builder and Singleton are the classic five. - **Instance**: one concrete object in memory, with its own field values. - **Prototype (here)**: an already-existing, already-configured instance that is kept around specifically so that other objects can be produced from it by copying. - **Clone / copy**: produce a new object whose state is equivalent to an existing one. ### The intent > *Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.* Normal object creation is **construction**: call a constructor, then run whatever setup the object needs. Prototype replaces that with **duplication**: take an object that is already in the desired state and ask it for a copy. ### Shape of the pattern Three roles: 1. **Prototype** — an abstract type (interface/abstract class) declaring a copy operation, e.g. `Shape { Shape clone() }`. 2. **ConcretePrototype** — each real class implements the copy operation, returning a new object of its own type. 3. **Client** — holds a `Shape` reference and calls `clone()`. It never names `Circle`, `Polygon`, `BezierPath`, and never knows how any of them are built. Optionally there is a fourth role, the **prototype registry** (a.k.a. prototype manager): a map from key → configured prototype, so `registry.get("warning-dialog").clone()` yields a ready-made object. ### Why you would reach for it - **Expensive instantiation.** The object's real cost is not allocating memory but the work behind it: reading a file, parsing a grammar, compiling a regex, warming a lookup table, doing a database round-trip. If that work produces a value that can be copied cheaply, do it once into a prototype and clone thereafter. - **Configuration-heavy setup.** An object needing 15 options set in a precise order is error-prone to build repeatedly. Build one exemplar, validate it, then clone-and-tweak: `var d = defaultDialog.clone(); d.title = "Delete?";`. - **Runtime-decided variants.** Instead of a `switch` over types (which must be edited for every new variant) or one factory subclass per product, you *register instances*. Adding a new variant becomes adding data — a new configured prototype — not new code. Graphical editors do exactly this: a palette of tools where each tool is a prototype shape; dropping one onto the canvas clones it. - **Preserving state you cannot reconstruct.** Sometimes the only way to get an object into a given state is to have gone through the interactions that got it there. Copying preserves it; constructing cannot. - **Undo/snapshot-style features** often lean on the same copy machinery (though the *pattern* for that is Memento). ### Why it is riskier than it looks The pattern's whole substance collapses into one question: **what does "a copy" mean for this object?** - A **shallow copy** duplicates the object's own fields; fields that are references still point at the *same* nested objects, now shared between original and copy. Mutating a shared nested object is visible through both — action at a distance, a classic aliasing bug. - A **deep copy** recursively duplicates the reachable object graph, so the copy is independent. It costs more time and memory, and it must cope with shared references and cycles, and with parts that *must not* be duplicated (identities, open connections, locks, listeners). So Prototype is trivial to draw and non-trivial to get right; the difficulty lives in the copy, not in the pattern diagram. ### Relation to neighbouring patterns - **Factory Method / Abstract Factory** create by *calling code* keyed on a type; Prototype creates by *copying data*. Factories tend to need a class per product; Prototype needs an instance per variant. - **Builder** assembles a complex object step by step; Prototype skips assembly by reusing a finished one. They combine well: build once, clone many. - **Memento** captures state for later restoration rather than for producing sibling objects. - **Flyweight** deliberately *shares* instead of copying — the opposite trade-off, valid when the state is immutable. ### When *not* to use it If objects are immutable, copying is pointless — share the instance instead. If construction is cheap and clear, a constructor or factory is easier to read and to test. If the object owns external resources (sockets, file handles, threads), "copy" may have no coherent meaning and the pattern will invite bugs.

  • How is Prototype different from a factory that returns preconfigured objects?
    A factory builds by executing construction code chosen by type key, so a new variant usually means new code (a branch, a subclass). Prototype builds by duplicating a stored instance, so a new variant is a new piece of data — register another configured exemplar. Prototype also preserves state that construction could not reproduce.
  • If a class is immutable, is Prototype still useful?
    Rarely for copying — immutable objects can be shared safely, so cloning only wastes memory. Prototype still has value as a way to keep a catalogue of ready-made exemplars, but the copy operation itself can legitimately return `this`.

A print shop keeps a signed master copy of a poster. Producing another poster means running the master through the copier, not re-drawing the artwork. The master is the prototype; the copier is clone(). The catch: if the master has a real ribbon glued to it, the copy only gets a picture of the ribbon — that gap is the shallow-versus-deep-copy problem.

saying these in an interview costs you the question

  • "Prototype is just another name for a factory" — factories execute construction code, Prototype duplicates an existing instance.
  • Assuming `clone()` is automatically a deep copy.
  • Using Prototype for immutable objects, where sharing is strictly better.
  • Cloning objects that own external resources (sockets, handles, threads) as if the resource could be duplicated.
  • Thinking the pattern is complete once a `clone()` method exists, without deciding per-field copy semantics.

context