Design Patterns    |     Security    |     Testing    |     Distributed Computing    |     Contact

Prototype Design Pattern, UML diagram, Java Example

             

Definition

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

Class Diagram

Builder

Participants

  • Prototype
    • declares an interface for cloning itself.
  • ConcretePrototype.
    • implements an operation for cloning itself.
  • Client.
    • creates a new object by asking a prototype to clone itself.

Example: Product Cache

When object instantiation is a lot more expensive than cloning, Prototype pattern may offer a useful optimization technique.

Example assumptions:

  • An e-commerce application gathers product information trough complex queries against a legacy database.
  • The legacy database is updated at predefined intervals which are known.
  • The number of products allows caching with a reasonable memory consumption.

When a user asks for information for a certain product the application could gather that information in two ways:

  1. execute the complex query against legacy database, gather the information, and instantiate the object.
  2. instantiate the objects at predefined intervals and keep them in a cache, when an object is requested, it is retrieved from cache and cloned. When the legacy database is updated, discard the content of the cache and re-load with new objects.

The second approach is based on Prototype pattern and it is illustrated below:

Example: Class Diagram

Prototype Example

Example: Java sample code

    	package com.apwebco.patterns.gof.prototype;
	
	public abstract class Product implements Cloneable {
		private String SKU;
		private String description;	
		
		public Object clone() {
			Object clone = null;
			try {
				clone = super.clone();
			} catch (CloneNotSupportedException e) {
				e.printStackTrace();
			}
			return clone;
		}
		public String getDescription() {
			return description;
		}
		public String getSKU() {
			return SKU;
		}
		public void setDescription(String string) {
			description = string;
		}
		public void setSKU(String string) {
			SKU = string;
		}
	}
	public class Book extends Product {
		private int numberOfPages;

		public int getNumberOfPages() {
			return numberOfPages;
		}
		public void setNumberOfPages(int i) {
			numberOfPages = i;
		}
	}
	public class DVD extends Product {
		private int duration;

		public int getDuration() {
			return duration;
		}
		public void setDuration(int i) {
			duration = i;
		}
	}
	import java.util.*;
	public class ProductCache {
		private static Hashtable productMap = new Hashtable();

		public static Product getProduct(String productCode) {
			Product cachedProduct = (Product) productMap.get(productCode);
			return (Product) cachedProduct.clone();
		}

		public static void loadCache() {
			// for each product run expensive query and instantiate product
			// productMap.put(productKey, product);
			// for exemplification, we add only two products
			Book b1 = new Book();
			b1.setDescription("Oliver Twist");
			b1.setSKU("B1");
			b1.setNumberOfPages(100);
			productMap.put(b1.getSKU(), b1);
			DVD d1 = new DVD();
			d1.setDescription("Superman");
			d1.setSKU("D1");
			d1.setDuration(180);
			productMap.put(d1.getSKU(), d1);
		}
	}
	public class Application {
		public static void main(String[] args) {
			ProductCache.loadCache();

			Book clonedBook = (Book) ProductCache.getProduct("B1");
			System.out.println("SKU = " + clonedBook.getSKU());
			System.out.println("SKU = " + clonedBook.getDescription());
			System.out.println("SKU = " + clonedBook.getNumberOfPages());

			DVD clonedDVD = (DVD) ProductCache.getProduct("D1");
			System.out.println("SKU = " + clonedDVD.getSKU());
			System.out.println("SKU = " + clonedDVD.getDescription());
			System.out.println("SKU = " + clonedDVD.getDuration());
		}
	}
    	

Benefits

  • 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 dinamincally.

Usage

  • When the classes to instantiate are specified at run time.
  • When you want to avoid building a class hierarchy of factories that parallels the class hierarchy of products.
  • When instances of a class can have one of only a few combinations of state.