Prototype

Lets you copy existing objects without making your code dependent on their classes.

classDiagram
    class Prototype {
        <<interface>>
        +clone() Prototype
    }
    class ConcretePrototype1 {
        -field1
        +clone() Prototype
    }
    class ConcretePrototype2 {
        -field2
        +clone() Prototype
    }
    class Client {
        -Prototype prototype
        +operation()
    }

    Prototype <|.. ConcretePrototype1
    Prototype <|.. ConcretePrototype2
    Client --> Prototype

When to use

Use when your code shouldn’t depend on the concrete classes of objects that you need to copy. This happens a lot when your code works with objects passed to you from 3rd-party code via some interface.

Explanation

Problem

Say you have an object, and you want to create an exact copy of it. How would you do it? First, you have to create a new object of the same class. Then you have to go through all the fields of the original object and copy their values over to the new object. But not all objects can be copied that way because some of the object’s fields may be private and not visible from outside of the object itself.

Solution

The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object.

Real world problem

  1. Cell Division: Mitosis. A cell splits into two identical copies.
  2. Versioning: In Google Docs or Git, creating a branching version starts as a copy of the current state.
  3. Game Assets: Spawning “mobs” in a game. You create one “Goblin” as a prototype and clone it 100 times, modifying position/stats slightly.

Pros and Cons

Pros Cons
- Cloning: You can clone objects without coupling to their concrete classes.
- Presets: You can get rid of repeated initialization code in favor of cloning pre-built prototypes.
- Complex Objects: You can produce complex objects more conveniently.
- Circular References: Cloning complex objects that have circular references might be very tricky.

Comparison

  • Factory Method: Factory methods are often used to create the initial prototypes.
  • Abstract Factory: Abstract Factory can store a set of prototypes from which to clone and return product objects.
  • Snapshot (Memento): Memento saves state to an external object. Prototype saves state to a new object of the same class.

Code example

Typescript

Php