Prototype
Let objects copy themselves through a shared clone method, so client code duplicates them without knowing their concrete classes.
The problem
You have an object and you want an exact copy. The obvious move is to make a new object of the same class and copy the fields across. Two things go wrong immediately.
Some of those fields are private and simply not visible from outside. And to write the copy at all you must name the concrete class, which welds your code to it - awkward, given you often only know the interface the object implements, not what it actually is.
The solution
Delegate the copying to the object itself. Declare a common interface for anything
copyable - usually a single clone() method - and let each class implement it. Inside that
method the class can read its own private fields, because most languages let an object touch
private members of other instances of the same class.
The implementation is boringly uniform: a copy constructor that carries over the fields, and
a clone() that returns new MyClass(this). Subclasses call the parent copy constructor
first so inherited fields come along.
There is a second benefit that has nothing to do with privacy. When objects have dozens of fields and hundreds of plausible configurations, cloning replaces subclassing. Build a set of configured instances once, then clone whichever one you want instead of constructing from scratch. Keep them in a prototype registry - at its simplest, a name to prototype map - and pre-built configurations become lookups.
- 1At startup a few painstakingly configured instances are filed in the registry under readable names.
- 2Later, the client asks for that configuration by name. No constructor, no parameters, no subclass.
- 3The registry never hands out the stored object itself. It always returns a copy, so the catalog stays pristine.
- 4The prototype passes itself to its own copy constructor, which can read private fields because same-class access is allowed.
- 5The clone arrives typed as Shape. The client got a fully configured Circle without ever saying the word Circle.
- 6The same trick scales: iterate a mixed array, call clone() on every element, and polymorphism picks the right implementation each time.
Structure
The basic version is two boxes: a prototype interface declaring clone(), and concrete
prototypes implementing it. The registry variant adds a catalog in front, storing ready-made
instances and returning copies of them.
Code
Same example three ways: a shape hierarchy that duplicates itself, plus a registry of pre-configured shapes.
When to use it
- Your code must copy objects whose concrete classes it does not and should not know, which happens constantly with objects handed to you by third-party code behind an interface.
- You are accumulating subclasses that differ only in how they initialize themselves. Replace them with configured prototypes and a registry lookup.
- Reconstructing a complex object is expensive or fiddly, and copying a known-good one is both cheaper and less likely to be wrong.
Pitfalls
- Shallow by default. A field-by-field copy duplicates references, not the things they point at. Two "independent" clones sharing one mutable list is a fun afternoon of debugging.
- Circular references. Object graphs that point back at themselves make naive deep copies recurse forever. You need visited-set bookkeeping or a serialization trick.
- The forgotten override. A subclass without its own
clone()silently produces a parent-class object. Nothing complains until something downstream does. - Registries that hand out the original. If
get()returns the stored instance instead of a copy, the first caller to mutate it corrupts the catalog for everyone.
Don't confuse it with
- Copy constructors. A copy constructor is the mechanism Prototype uses; Prototype is the
polymorphic interface wrapped around it. Without
clone(), the caller is back to naming classes. - Factory Method. Prototype is not built on inheritance, so it dodges inheritance's drawbacks, but it requires a properly initialized object to copy. Factory Method needs the hierarchy and skips the setup.
- Memento. For snapshotting simple objects with no external links, a clone is often a perfectly good and much cheaper Memento.
Check yourself
Why does Prototype put the copying logic inside the object being copied?