本文参考自《设计模式之禅》,《Java与模式》
一、通过给出一个原型对象来指明所要创建的对象的类型。
二、Java中半支持
1.Ojbect类提供一个clone方法。
2.Java必须实现Cloneable来显式表明Javabean支持复制。
3.如果不实现Cloneable接口而直接使用,会抛出java.lang.CloneNotSupportedException。
4.默认的实现是浅拷贝,需要重写clone方法。
三、Code
package com.jue.dp; public class TV implements Cloneable { private int price; private Box box; public TV(Box b, int price) { this.box = b; this.price = price; System.out.println("TV()"); } public Box getBox() { return box; } public void setBox(Box box) { this.box = box; } void display() { System.out.println(box.name + " , " + price); } @Override protected TV clone() throws CloneNotSupportedException { TV temp = (TV) super.clone(); temp.box = box.clone(); return temp; } }
package com.jue.dp; public class Box implements Cloneable { public String name = "default"; @Override protected Box clone() throws CloneNotSupportedException { return (Box) super.clone(); } }
package com.jue.dp; public class MainClass { public static void main(String[] args) throws CloneNotSupportedException { Box b1 = new Box(); TV t1 = new TV(b1, 100); t1.display(); System.out.println("------------------------"); TV t2 = t1.clone(); t2.display(); System.out.println("------------------------"); b1.name = "changed"; t1.display(); t2.display(); } }
四、优点
1.原型模式是在内存中二进制流的拷贝,比直接new一个对象性能要好很多。
2.直接在内存中拷贝,构造函数不会执行。
3.能够获取一个即时状态的值。
五、缺点
1.构造器不会执行。
六、注意点
1.Object的clone如果只是调用super.clone,复合类型只是浅拷贝(对象中的数组对象,其他复合对象,但是String是深拷贝)。
2.Clone与final常量有冲突,如下有编译错误。
package com.jue.dp; import java.util.ArrayList; public class Things implements Cloneable { private final ArrayList<String> arraylist = new ArrayList<String>(); @Override protected Object clone() throws CloneNotSupportedException { Things t = (Things) super.clone(); t.arraylist = (ArrayList<String>) this.arraylist.clone(); return super.clone(); } }
七、使用场景
1.类的初始化需要较多资源。
2.需要记录一个状态的对象的值。
3.使用new需要较为繁琐的准备和访问权限使用受限。