Card 01/ 08
Prototype Pattern: Creating Objects by Copying an Existing One
When an object is expensive to configure, copy a configured one instead of building it again.
The Prototype pattern creates new objects by copying an existing object, the prototype, instead of calling a constructor and configuring the result. This card covers the problems that make copying the better choice, the intent, and when the pattern is worth using.
Three problems lead to it. The set-up is costly, such as stats read from a file or a database. The set-up is long, a dozen fields that must be chosen the same way each time. Or the calling code does not know the object's class, only that it has an object of the right kind, and asking that object to copy itself is the one way to get another without naming the class.
Without the patternthe set-up repeated for each object
for position in spawn_points:
goblin = Enemy("goblin")
goblin.load_stats("goblin.json")
goblin.gear = ["club"]
goblin.position = positionThe file is read once for every goblin, and the configuration is written wherever goblins are made.
With the patternconfigure once, then copy
template = Enemy("goblin")
template.load_stats("goblin.json")
template.gear = ["club"]
for position in spawn_points:
goblin = template.clone()
goblin.position = positionThe configuration lives in one object, and each goblin starts as a copy of it.
The Gang of Four state the intent as: specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. The copy is made by the object itself, through a clone method, because only the object knows every field it holds.
Think of photocopying a filled-in form instead of filling in a blank one. The analogy breaks in one place: a photocopy duplicates every page, while the simplest copy of an object shares anything clipped to it, such as a list, with the original.
Prototype is one of five creational patterns, the family that controls how objects are created.
| Pattern | What it decides |
|---|---|
| Factory Method | Which class a subclass creates, through one overridable method. |
| Abstract Factory | Which family of related classes is created, through one object. |
| Builder | How a complex object is put together step by step. |
| Prototype (this topic) | Which existing object a new one is copied from. |
| Singleton | That a class has only one instance. |
Use it when
- Configuring an object is costly or long, and many objects start from the same configuration.
- The code that needs a new object knows only an existing object of the right kind, not its class.
- The kinds of object are data, such as enemy types loaded at start-up, rather than classes written in code.
Avoid it when
- A constructor call is cheap and clear.
- The object holds resources that cannot be copied meaningfully, such as an open file or a network connection.
- Its nested objects make a correct copy hard to define, and nobody will keep that definition up to date.
← → move through sections and cards