Design Patterns Tutorial
A tutorial on GOF design patterns. This tutorial is for beginners who are going to learn design patterns for the first time. Each pattern is expalined with suitable examples.

24/11/2013 Categories: Creational Patterns. No Comments on Prototype Pattern

Intent:

To specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

 

Motivation:

A prototype is a template of any object before the actual object is constructed. In java also, it holds the same meaning. Prototype design pattern is used in scenarios where application needs to create a number of instances of a class, which has almost same state or differs very little.

In this design pattern, an instance of actual object (i.e. prototype) is created on starting, and thereafter whenever a new instance is required, this prototype is cloned to have another instance. The main advantage of this pattern is to have minimal instance creation process which is much costly than cloning process.

Some of the situations where the prototype pattern can be applied are given below:

 

Example 1:

In building stages for a game that uses a maze and different visual objects that the character encounters it is needed a quick method of generating the haze map using the same objects: wall, door, passage, room… The Prototype pattern is useful in this case because instead of hard coding (using new operation) the room, door, passage and wall objects that get instantiated, CreateMaze method will be parameterized by various prototypical room, door, wall and passage objects, so the composition of the map can be easily changed by replacing the prototypical objects with different ones.

The Client is the CreateMaze method and the ConcretePrototype classes will be the ones creating copies for different objects.

 

Example 2:

Suppose we are doing a sales analysis on a set of data from a database. Normally, we would copy the information from the database, encapsulate it into an object and do the analysis. But if another analysis is needed on the same set of data, reading the database again and creating a new object is not the best idea. If we are using the Prototype pattern then the object used in the first analysis will be cloned and used for the other analysis.

The Client methods process the object that encapsulates information from the database. The ConcretePrototype class will be class that creates the object after extracting data from the database, will copy it into objects used for analysis.

 

Applicability:

Use prototype pattern when a system should be independent of how its products are created, composed and represented and:

  •  When the class to be instantiated is specified at runtime or
  •  To avoid building a hierarchy of factory classes or
  •  It is more convenient to clone an object rather than creating a new object.


Structure:

prototype pattern structure

 

Participants:

The classes participating to the Prototype Pattern are:

Client – creates a new object by asking a prototype to clone itself.

Prototype – declares an interface for cloning itself.

ConcretePrototype – implements the operation for cloning itself.

 

Collaborations:

A client asks a prototype to clone itself.

 

Consequences:

Benefits of prototype pattern are:

  •  Adding and removing products at runtime.
  •  Specifying new objects by varying values.
  •  Specifying new objects by varying structure.
  •  Reduced subclassing.
  •  Configuring an application with classes dynamically.

 

Main drawback of prototype pattern is that each sub class of Prototype must implement the clone operation, which may be difficult.

 

Implementation:

abstract class AbstractProduct implements Cloneable 
{
	public static AbstractProduct thePrototype;
	public static AbstractProduct makeProduct()
	{
		try 
		{
			return (AbstractProduct) thePrototype.clone();
	   	 } 
		catch(CloneNotSupportedException e)
		{
			return null;
	   	 }
	}
}

class ConcreteProductA extends AbstractProduct { }

class ConcreteProductB extends AbstractProduct { }

public class PrototypeDemo 
{
	public static void main(String[] args) 
	{
		AbstractProduct.thePrototype = new ConcreteProductA();
		AbstractProduct product = AbstractProduct.makeProduct();
		System.out.println(product);
	}
}

 

Implementation Issues:

Using a prototype manager:

When the application uses a lot of prototypes that can be created and destroyed dynamically, a registry of available prototypes should be kept. This registry is called the prototype manager and it should implement operations for managing registered prototypes like registering a prototype under a certain key, searching for a prototype with a given key, removing one from the register, etc. The clients will use the interface of the prototype manager to handle prototypes at run-time and will ask for permission before using the Clone() method.

There is not much difference between an implementation of a prototype which uses a prototype manager and a factory method implemented using class registration mechanism. Maybe the only difference consists in the performance.

 

Implementing the Clone operation:

A small discussion appears when talking about how deep or shallow a clone should be: a deep clone clones the instance variables in the cloning object while a shallow clone shares the instance variables between the clone and the original. Usually, a shallow clone is enough and very simple, but cloning complex prototypes should use deep clones so the clone and the original are independent, a deep clone needing its components to be the clones of the complex object’s components.

 

Initializing clones:

There are cases when the internal states of a clone should be initialized after it is created. This happens because these values cannot be passed to the Clone() method, that uses an interface which would be destroyed if such parameters were used. In this case the initialization should be done by using setting and resetting operations of the prototype class or by using an initializing method that takes as parameters the values at which the clone’s internal states should be set.


Sample Code:

We’re going to create an abstract class Shape and concrete classes extending the Shape class. A class ShapeCache is defined as a next step which stores shape objects in a Hashtable and returns their clone when requested.

Create an abstract class implementing Clonable interface.

 Shape.java

public abstract class Shape implements Cloneable 
{   
	private String id;
	protected String type;
   	abstract void draw();
   	public String getType()
	{
		return type;
	}   
	public String getId() 
	{
	  return id;
	}   
	public void setId(String id) 
	{
		this.id = id;
	}   
	public Object clone()
	{
		Object clone = null;
		try 
		{
			clone = super.clone();
		} 
		catch (CloneNotSupportedException e) 
		{
			e.printStackTrace();
		}
		return clone;
	}
}

Create concrete classes extending the above class.

 

Rectangle.java

public class Rectangle extends Shape 
{
	public Rectangle()
	{
		type = "Rectangle";
	}
	@Override
	public void draw() 
	{
		System.out.println("Inside Rectangle::draw() method.");
	}
}

Square.java

public class Square extends Shape 
{
	public Square()
	{
		type = "Square";
	}
	@Override
	public void draw() 
	{
		System.out.println("Inside Square::draw() method.");
	}
}

Circle.java

public class Circle extends Shape 
{
	public Circle()
	{
		type = "Circle";
	}
	@Override
	public void draw() 
	{
		System.out.println("Inside Circle::draw() method.");
	}
}

Create a class to get concreate classes from database and store them in a Hashtable.

 

ShapeCache.java

import java.util.Hashtable;
public class ShapeCache 
{	
	private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();
	public static Shape getShape(String shapeId) 
	{
		Shape cachedShape = shapeMap.get(shapeId);
		return (Shape) cachedShape.clone();
	}
	public static void loadCache() 
	{
		Circle circle = new Circle();
		circle.setId("1");
		shapeMap.put(circle.getId(),circle);
		Square square = new Square();
		square.setId("2");
		shapeMap.put(square.getId(),square);
		Rectangle rectangle = new Rectangle();
		rectangle.setId("3");
		shapeMap.put(rectangle.getId(),rectangle);
	}
}

PrototypePatternDemo uses ShapeCache class to get clones of shapes stored in a Hashtable.

 

PrototypePatternDemo.java

public class PrototypePatternDemo 
{
	public static void main(String[] args) 
	{
		ShapeCache.loadCache();
		Shape clonedShape = (Shape) ShapeCache.getShape("1");
		System.out.println("Shape : " + clonedShape.getType());		
		Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
		System.out.println("Shape : " + clonedShape2.getType());		
		Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
		System.out.println("Shape : " + clonedShape3.getType());		
	}
}

 

prototype pattern real world example

 

Known Uses:

The first widely known application of the pattern in an object-oriented language was in ThingLab, where users could form a composite object and then promote it to a prototype by installing it in a library of reusable objects. Prototype is used in Etgdb. Etgdb is a debugger front-end based on ET++ that provides a point-and-click interface to different line-oriented debuggers. The “interaction technique library” in Mode Composer stores prototypes of objects that support various interaction techniques.

 

Related Patterns:

Prototype and Abstract Factory patterns can be used together. Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

Example prototype classes in Java API:

java.lang.Object#clone() (the class has to implement java.lang.Cloneable)

 

Non-software example:

The Prototype pattern specifies the kind of objects to create using a prototypical instance. Prototypes of new products are often built prior to full production, but in this example, the prototype is passive, and does not participate in copying itself. The mitotic division of a cell, resulting in two identical cells, is an example of a prototype that plays an active role in copying itself and thus, demonstrates the Prototype pattern. When a cell splits, two cells of identical genotype result. In other words, the cell clones itself.

 

prototype pattern non software example

Suryateja Pericherla

Suryateja Pericherla

Hello, I am Suryateja Pericherla working as an Asst. Professor in CSE department at Vishnu Institute of Technology. I write articles to share my knowledge and make people knowledgeable regarding certain topics.
Suryateja Pericherla

Latest posts by Suryateja Pericherla (see all)

Related Links:

Note: Do you have a question on this article or have a suggestion to make this article better? You can ask or suggest us by filling in the below form. After commenting, your comment will be held for moderation and will be published in 24-48 hrs.
Scroll Up