Your Guide to Design Patterns – Prototype Pattern

Design Patterns - Prototype Pattern

In the first of this design patterns series, we looked at one of the creational design patterns, the singleton pattern. This week we’ll look at another creational pattern, the Prototype design pattern. Remember that creational patterns are concerned with the best way to create instances of objects.

The Gang of Four book defines the prototype pattern as follows:

“Specify the kind of objects to create using a prototypical instance and create new objects by copying this prototype”.

All prototype classes should have a common interface that makes it possible to copy objects even if their concrete classes are unknown. Prototype objects can produce full copies since objects of the same class can access each other’s private fields.

The prototype can be easily recognized by having a clone() or copy() method.

Prototype Pattern Usage

The prototype design pattern is used when object creation has a high cost in terms of time and resources, and when we already have a similar previously instantiated object.

When should we use the prototype pattern?

  • When the classes are instantiated on the fly during runtime.
  • When the cost of creating an object is expensive, resource-intensive or complicated.
  • When we want to hide the complexities of creating objects.

The pattern provides a mechanism to copy the original object to a new object and then modify it according to our needs. Instead of creating new objects, we simply clone the prototypical instance. The prototype clones itself and creates a new object. The cloning isn’t done by any other class; rather the class itself provides the copying method. The clients of the class can create any number of new objects without knowing which type of object they will be.

Prototype Pattern: The Cloneable Interface

The prototype pattern is available in Java out of the box with the java.lang.Cloneable interface. Any class can implement this interface by overriding the clone() method.

When overriding the clone() method, we need to decide between making a shallow copy or a deep copy. This is based on the actual system requirements, but is usually done as follows:

  • If the class contains only primitive and immutable fields, we can do a shallow copy. This is a field by field copy – we copy the field value of the original object to the same field in the cloned object.
  • If the class contains references to mutable fields, we should do a deep copy. A deep copy is when we make copies of all the objects that are referenced by the original object.

Cloning Mechanisms

We have a variety of coding mechanisms to clone an object:

  • We can implement the Cloneable interface as explained earlier.
  • We can create a copy constructor. This is a constructor that takes in an object of the same class. THis will generally make a deep copy. We can even use the copy constructor in a clone() method by passing the this reference as the argument to the copy constructor.
  • We can use serialization and deserialization with a ByteArrayInputStream and a ByteArrayOutputStream.

Prototype Pattern: Example Code

Let’s say we’re busy creating our first person shooter game populated with assorted monsters. We’ve decided that we want to create a zombie horde as a challenge for the player. Obviously we could create a multitude of zombies by calling their constructors with the new keyword.

Suppose we have to read data from our monster database before we can create a zombie. Then we have to modify this data in our game multiple times for each zombie. It won’t a good idea to create zombies using the new keyword each time, and having to load the same or similar data again from the database. This would make the creation of a zombie horde very time-consuming.

A much better solution would be to create a single prototypical instance of a Zombie, and then simply clone it over and over to create our fearsome horde of zombies.

To allow this cloning, we would implement the java.lang.Cloneable interface:

public class Zombie implements java.lang.Cloneable {

   // other code

   @Override
   public Object clone() {
      // appropriate code
   }
}

The clone() method has protected access in the Object class. We would override this method with a public method. The customary first step in any clone() implementation is to invoke the superclass’s implementation of clone():

public Object clone() throws CloneNotSupportedException {
   «type» cloned = («type»)super.clone();  // type cast to correct class type
   cloned.mutableField   = (MutableField) mutableField.clone();
   cloned.immutableField = immutableField;
   cloned.primitiveField = primitiveField;
   ...
   return cloned;
}

If we are writing a clone() method for a direct subclass of Object, we will need to either catch CloneNotSupportedException or declare it in the throws clause. The Object class does a shallow field-by-field copy in low-level native code.

We could alternatively create a copy constructor, and call it from the overridden clone() method. The requirements and mechanics of a copy constructor are possibly easier to understand than that of the clone() method. Sample code follows:

public class Zombie implements java.lang.Cloneable {

   // other code

   public Zombie (Zombie zombie) {
      // appropriate code - easy to understand
   }

   @Override
   public Object clone() {
      return new Zombie(this);
   }
}

As you see, the prototype pattern is a relatively simple pattern to understand and implement.

What’s next?

In the weeks ahead, we’ll continue examining some of the more useful design patterns. Stay tuned!

As always, please share your comments and questions.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.