原型模式的本质:
原型模式的本质就是通过克隆的手段进行复制对象,当一个对象的构造函数十分复杂的时候,在他实例化的时候需要耗费大量的资源或者执行很多的方法,这个时候用到原型模式会节省很多的时间。
原型模式在进行克隆的时候,并没有调用类的构造器,而是通过通过Object中的clone()方法从堆内存中通过二进制流的方式进行拷贝,重新分配了一块内存。
原型模式的俩种方式:
浅克隆的定义:浅克隆就是对值类型的成员变量进行值的复制,对引用类型的成员变量只复制他的引用,不复制引用的对象
分析:在java中通过覆盖Object中的clone()方法就是进行浅克隆,在浅克隆中在对象被复制的时候只复制他本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有被复制,也就是说原型对象只是将引用类型的地址复制给一份给克隆对象,克隆对象和原型对象的引用类型成员变量还是指向相同的内存地址。
深克隆定义:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
分析:在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,简单来说,在深克隆中,除了对象本身被复制以外,对象所包含的所有成员变量也将复制。
用代码实现俩种克隆:
浅克隆:
public class Sheep implements Cloneable,Serializable { //1997,英国的克隆羊,多利!
private String sname;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone(); //直接调用object对象的clone()方法!
return obj;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sheep(String sname, Date birthday) {
super();
this.sname = sname;
this.birthday = birthday;
}
public Sheep() {
}
}
浅克隆client:
public class Client {
public static void main(String[] args) throws Exception {
Date date = new Date(12312321331L);
Sheep s1 = new Sheep("少利", date);
System.out.println(s1);
System.out.println(s1.getSname());
System.out.println(s1.getBirthday());
date.setTime(23432432423L);
System.out.println(s1.getBirthday());
Sheep s2 = (Sheep) s1.clone();
s2.setSname("多利");
System.out.println(s2);
System.out.println(s2.getSname());
System.out.println(s2.getBirthday());
}
}
深克隆:
public class Sheep2 implements Cloneable { //1997,英国的克隆羊,多利!
private String sname;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone(); //直接调用object对象的clone()方法!
//添加如下代码实现深复制(deep Clone)
Sheep2 s = (Sheep2) obj;
s.birthday = (Date) this.birthday.clone(); //把属性也进行克隆!
return obj;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sheep2(String sname, Date birthday) {
super();
this.sname = sname;
this.birthday = birthday;
}
public Sheep2() {
}
}
深克隆client:
public class Client2 {
public static void main(String[] args) throws CloneNotSupportedException {
Date date = new Date(12312321331L);
Sheep2 s1 = new Sheep2("少利", date);
Sheep2 s2 = (Sheep2) s1.clone(); //实现深复制。s2对象的birthday是一个新对象!
System.out.println(s1);
System.out.println(s1.getSname());
System.out.println(s1.getBirthday());
date.setTime(23432432423L);
System.out.println(s1.getBirthday());
s2.setSname("多利");
System.out.println(s2);
System.out.println(s2.getSname());
System.out.println(s2.getBirthday());
}
}
序列化实现深复制:
public class Client3 {
public static void main(String[] args) throws CloneNotSupportedException, Exception {
Date date = new Date(12312321331L);
Sheep s1 = new Sheep("少利", date);
System.out.println(s1);
System.out.println(s1.getSname());
System.out.println(s1.getBirthday());
//使用序列化和反序列化实现深复制
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Sheep s2 = (Sheep) ois.readObject(); //克隆好的对象!
System.out.println("修改原型对象的属性值");
date.setTime(23432432423L);
System.out.println(s1.getBirthday());
s2.setSname("多利");
System.out.println(s2);
System.out.println(s2.getSname());
System.out.println(s2.getBirthday());
}
}
效率测试:
public class Client04 {
public static void testNew(int size){
long start = System.currentTimeMillis();
for(int i=0;i<size;i++){
Laptop t = new Laptop();
}
long end = System.currentTimeMillis();
System.out.println("new的方式创建耗时:"+(end-start));
}
public static void testClone(int size) throws CloneNotSupportedException{
long start = System.currentTimeMillis();
Laptop t = new Laptop();
for(int i=0;i<size;i++){
Laptop temp = (Laptop) t.clone();
}
long end = System.currentTimeMillis();
System.out.println("clone的方式创建耗时:"+(end-start));
}
public static void main(String[] args) throws Exception {
testNew(1000);
testClone(1000);
}
}
class Laptop implements Cloneable { //笔记本电脑
public Laptop() {
try {
Thread.sleep(10); //模拟创建对象耗时的过程!
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone(); //直接调用object对象的clone()方法!
return obj;
}
}
时间比较
new的方式创建耗时:10301
clone的方式创建耗时:10