Card 01/ 08

ConceptDifficulty: Intermediate2 min

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.

Configuring every object and copying one

Without the patternthe set-up repeated for each object

py
for position in spawn_points:
    goblin = Enemy("goblin")
    goblin.load_stats("goblin.json")
    goblin.gear = ["club"]
    goblin.position = position

The file is read once for every goblin, and the configuration is written wherever goblins are made.

With the patternconfigure once, then copy

py
template = Enemy("goblin")
template.load_stats("goblin.json")
template.gear = ["club"]
for position in spawn_points:
    goblin = template.clone()
    goblin.position = position

The 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.

The creational family, with this pattern marked
PatternWhat it decides
Factory MethodWhich class a subclass creates, through one overridable method.
Abstract FactoryWhich family of related classes is created, through one object.
BuilderHow a complex object is put together step by step.
Prototype (this topic)Which existing object a new one is copied from.
SingletonThat a class has only one instance.
Prototype

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