The Prototype Pattern

The Prototype Pattern has purpose to simplify the creation of complex objects by copying them. An existing (partially or fully constructed) design is a Prototype. Let’s illustrate this with a Recipe object:

class Recipe {
  List<String> ingredients;
  List<String> utensils;
  int timeToPrepare;
  int timeToCook;

  ...
}

Let’s say we want to create a bunch of cake recipe. We want to create a basic recipe that can be completed later:

Recipe prototypeCake = new Recipe();
prototypeCake.addIngredient("Flour");
prototypeCake.addIngredient("Eggs");
...
prototypeCake.addUtensil("Bowl");
prototypeCake.addUtensil("Mixer");
...

Now time for the most complex part of the pattern: cloning the prototype. It requires to deep copy every single property (when needed).

class Recipe {
   ...

   public static Recipe clone(Recipe toClone) {
      Recipe copy = new Recipe();
      copy.timeToPrepare = toClone.timeToPrepare;
      copy.timeToCook = toClone.timeToCook;
      toClone.ingredients.forEach(copy::addIngredient);
      toClone.utensils.forEach(copy::addUtensil);
   }
}

// The creation of other recipes becomes much easier
Recipe chocolateCake = Recipe.clone(prototypeCake);
...
Recipe strawberryCake = Recipe.clone(prototypeCake);
...
Recipe cheeseCake = Recipe.clone(prototypeCake);
...

The difficulty with cloning is the to figure out how to copy the whole tree of objects that is needed. What if the list of ingredients was not a list of String but of Ingredient objects?

List<Ingredient> ingredients;

class Ingredient {
  double quantity;
  String description;
  Quality quality;
  double price;
  ...
}

We would need to deep copy Ingredient, and Quality, etc… Another way to clone is to use Java’s serialization mechanism which allows to copy the whole tree of objects by values.

So now, we can customize the objects:

chocolateCake.addIngredient("Chocolate");
etc...