0 XP · 0 scenes

Prototype

Make new objects by copying an existing one
The problem

Creating an Enemy means loading models, stats and sounds, which is slow.

The idea

Give the object a copy() method.

Reach for it when

Building an object is costly but copying is cheap

1

The picture from life

A teacher has a master worksheet with the school name, layout and instructions. For every student she photocopies it and then writes a name on the copy. She does not retype the whole sheet each time, and writing on a copy leaves the master unchanged.

2

The problem

What goes wrong when you do not use it.

Creating an Enemy means loading models, stats and sounds, which is slow. Spawning a hundred goblins this way takes seconds, even though they are all the same except for position.

✗ Before
for 100 timesEnemy('goblin')# loads models and stats# every single timeEnemy__init__() is slow100 × slow
  • creates
Every new enemy runs the slow set-up from scratch.
Reach for it when
  • Building an object is costly but copying is cheap
  • Many objects differ only slightly from a template
  • You do not want to depend on the concrete class when copying
3

The idea

How the pattern fixes it.

Give the object a copy() method. Build one fully loaded prototype, then clone it and change only what differs. Remember to copy inner mutable parts too (a deep copy) so clones do not share them.

✓ After
templatekind: goblinitems: []goblin 1goblin 2goblin 3copy()copy()copy()
  • creates
Set up one template once. New enemies are quick copies of it.

Who is who

Enemy
The prototype. Knows how to copy itself.
copy()
Returns an independent duplicate (deep for inner lists).
Registry (optional)
A shelf of ready prototypes by name.

Build it in steps

  1. 1Build one fully prepared object once.
  2. 2Add copy() that duplicates it, including nested data.
  3. 3Clone it each time you need a new one.
  4. 4Change only the parts that differ.
4

Watch it run

Step through the calls. Tap an arrow to jump to it.

Clienttemplategoblin 1goblin 21copy()2deepcopy(self)3copy()4deepcopy(self)5items.append('sword')
Step 1/5

Ask the template for a copy. The slow loading is not repeated.

copy()
5

The code

Python and Java. Try writing the classes yourself from the diagram first.

import copy


class Enemy:
    def __init__(self, kind):
        self.kind = kind                    # imagine slow loading here
        self.items = []
        self.position = 0

    def copy(self):
        return copy.deepcopy(self)          # deep: the items list is copied too


def demo():
    template = Enemy("goblin")
    first = template.copy()
    second = template.copy()
    first.position = 10
    second.items.append("sword")
    return template.position, first.position, template.items, first.items, second.items

What you gain

  • Skips costly set-up
  • Clone without knowing the concrete class

What it costs

  • Deep copying cyclic or complex objects is tricky
  • Forgetting a nested field makes clones secretly share state

You have already met it in

  • JavaScript's prototype chain and Object.create
  • Java's Cloneable / clone() and Python's copy module
  • Duplicating a slide or a spreadsheet tab

Often mixed up with

  • BuilderPrototype copies something that already exists; Builder assembles a new thing step by step.
  • MementoMemento stores a snapshot so you can go back; Prototype makes a living duplicate to use.
6

Make it stick

Make a Document prototype with a list of paragraphs. Clone it twice, edit each clone differently and prove the original and the other clone did not change.

Confidence