Home
Core Java
Java
JDBC
Servlets
JSP
EJB
JMS
Struts
Spring
Hibernate
JSF
RMI
CORBA
J2ME
Performance
Tomcat
Weblogic
Design Patterns
Junit
XML
UML
DB2 & SQL
ANT
Free Gift
Contact Us

XML RSS
What is this?
Add to My Yahoo!
Add to My MSN
Add to Google
 

Creational Pattern

Prototype Pattern

Your Ad Here

Creational patterns Structural patterns Behavioral pattern J2EE patterns
Abstract Factory Adapter  Chain of Responsibility
MVC 
Builder Bridge  Command  Business Delegate
Factory method Composite  Interpreter  Composite Entity
Prototype Decorator  Iterator  Data Access Object
Singleton Façade
Mediator  Front Controller

Flyweight  Memento  Intercepting Filter

Proxy  Observer  Service Locator


State  Transfer Object


Strategy 


Template Method



Visitor 

Prototype Pattern



Define Prototype pattern
Cloning an object by reducing the cost of creation.

Where to use & benefits
When there are many subclasses that differ only in the kind of objects,
A system needs independent of how its objects are created, composed, and represented.
Dynamic binding or loading a method.
Use one instance to finish job just by changing its state or parameters.
Add and remove objects at runtime.
Specify new objects by changing its structure.
Configure an application with classes dynamically.

Related patterns include
  • Abstract Factory, which is often used together with prototype. An abstract factory may store some prototypes for cloning and returning objects.
  • Composite, which is often used with prototypes to make a part-whole relationship.
  • Decorator, which is used to add additional functionality to the prototype.

Your Ad Here
Example of prototype pattern
Dynamic loading is a typical object-oriented feature and prototype example. For example, overriding method is a kind of prototype pattern.

interface Shape {
   public void draw();
}
class Line implements Shape {
   public void draw() {
       System.out.println("line");
   }
}
class Square implements Shape {
   public void draw() {
       System.out.println("square");
   }
}
class Circle implements Shape {
   public void draw() {
       System.out.println("circle");
   }
}
class Painting {
    public static void main(String[] args) {
        Shape s1 = new Line();
        Shape s2 = new Square();
        Shape s3 = new Circle();
        paint(s1);
        paint(s2);
        paint(s3);
    }
    static void paint(Shape s) {
        if ( s instanceof Line)
           s.draw();
        if (s instanceof Square)
           s.draw();
        if (s instanceof Circle)
           s.draw();
    }
}

Out put is :
line
square
circle

The paint method takes a variable of Shape type at runtime. The draw method is called based on the runtime type.

Overloading method is a kind of prototype too.

class Painting {
   public void draw(Point p, Point p2) {
       //draw a line
   }
   public void draw(Point p, int x, int y) {
       //draw a square
   }
   public void draw(Point p, int x) {
       //draw a circle
   }
}

The draw method is called to draw the related shape based on the parameters it takes.

The prototype is typically used to clone an object, i.e. to make a copy of an object. When an object is complicated or time consuming to be created , you may take prototype pattern to make such object cloneable. Assume the Complex class is a complicated, you need to implement Cloneable interface and override the clone method(protected Object clone()).

class Complex implements Cloneable {
    int[] nums = {1,2,3,4,5};
    public Object clone() {
        try {
           return super.clone();
        }catch(CloneNotSupportedException cnse) {
            System.out.println(cnse.getMessage());
            return null;
        }
    }
    int[] getNums() {
       return nums;
    }
}
class Test {
   static Complex c1 = new Complex();
   static Complex makeCopy() {
      return (Complex)c1.clone();
   }
   public static void main(String[] args) {
       Complex c1 = makeCopy();
       int[] mycopy = c1.getNums();
       for(int i = 0; i < mycopy.length; i++)
          System.out.print(mycopy[i]);
   }
}

Outpput is :
12345

Cloning is a shallow copy of the original object. If the cloned object has been changed, the original object will be changed accordingly. See the following alteration.

class Complex implements Cloneable {
    int[] nums = {1,2,3,4,5};
    public Object clone() {
        try {
           return super.clone();
        }catch(CloneNotSupportedException cnse) {
            System.out.println(cnse.getMessage());
            return null;
        }
    }
    int[] getNums() {
       return nums;
    }
}
class Test {
   Complex c1 = new Complex();
   Complex makeCopy() {
      return (Complex)c1.clone();
   }
   public static void main(String[] args) {
       Test tp = new Test();
       Complex c2 = tp.makeCopy();
       int[] mycopy = c2.getNums();
       mycopy[0] = 5;

       System.out.println();
       System.out.print("local array: ");
       for(int i = 0; i < mycopy.length; i++)
          System.out.print(mycopy[i]);
       System.out.println();

       System.out.print("cloned object: ");
       for(int ii = 0; ii < c2.nums.length; ii++)
          System.out.print(c2.nums[ii]);
       System.out.println();

       System.out.print("original object: ");
       for(int iii = 0; iii < tp.c1.nums.length; iii++)
          System.out.print(tp.c1.nums[iii]);
}

Output is :
local array: 52345
cloned object: 52345
original object: 52345

To avoid such side effect, you may use a deep copy instead of a shallow copy. The following shows the alteration to the above example, note that the Complex class doesn't implement Cloneable interface.

class Complex {
    int[] nums = {1,2,3,4,5};
    public Complex clone() {
        return new Complex();
    }
    int[] getNums() {
       return nums;
    }
}
class Test2 {
   Complex c1 = new Complex();
   Complex makeCopy() {
      return (Complex)c1.clone();
   }
   public static void main(String[] args) {
       Test2 tp = new Test2();
       Complex c2 = tp.makeCopy();
       int[] mycopy = c2.getNums();
       mycopy[0] = 5;

       System.out.println();
       System.out.print("local array: ");
       for(int i = 0; i < mycopy.length; i++)
          System.out.print(mycopy[i]);
       System.out.println();

       System.out.print("cloned object: ");
       for(int ii = 0; ii < c2.nums.length; ii++)
          System.out.print(c2.nums[ii]);
       System.out.println();

       System.out.print("original object: ");
       for(int iii = 0; iii < tp.c1.nums.length; iii++)
          System.out.print(tp.c1.nums[iii]);
   }
}

Output :
local array: 52345
cloned object: 52345
original object: 12345


Your Ad Here




footer for Prototype Pattern page