Cloning an object by reducing the cost of creation.
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) { s.draw(); } } ---------------------------- If we want to make code more readable or do more stuff, we can code the paint method in the following way: static void paint(Shape s){ if ( s instanceof Line) s.draw(); //more job here if (s instanceof Square) s.draw(); //more job here if (s instanceof Circle) s.draw(); //more job here }
C:\> java Painting 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]); } }
C:\> java Test 12345 |
Cloning is a shallow copy of the original object. If the cloned object is 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]); }
C:\> java Test 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]); } }
C:\> java Test2 local array: 52345 cloned object: 52345 original object: 12345 |