1.如果需要创建大量类似的对象,如果用原型模式就可以节省大量时间。原型模式用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
2.原型模式的实现方式依赖java的 clone()方法,实现 Cloneable 就可以实现对象的克隆。克隆可分为浅克隆和深克隆两种方法,java的clone()是浅克隆。
(1)浅克隆:浅克隆会创建一个新对象,对原对象进行一个完全复制。如果原对象的属性是基本数据类型则进行值传递,如果是引用类型,则传引用。简而言之就是,浅克隆对于基本数据类型复制一个新的出来,新对象和原对象是两份,如果对于引用类型(对象)的属性,则把原来对象的内存地址赋给新对象,俩个引用类型的属性指向的内存地址相同,如果原对象指向地址值改了,克隆对象也会改变。
(2)深克隆:区别于浅克隆的是,不光对基本类型进行复制,还对引用类型进行复制。克隆对象和原对象是不同的两份,修改原对象对克隆对象没有影响。
3.实现浅克隆
package com.java.dp.copy; import lombok.Data; import lombok.ToString; /** * @Author lizhilong * @create 2019/12/2 15:33 * @desc */ @Data @ToString public class Student implements Cloneable{ private String name; private Integer age ; private Subject subject; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
package com.java.dp.copy; import lombok.Data; /** * @Author lizhilong * @create 2019/12/2 15:34 * @desc */ @Data public class Subject { private String name; private Double score; }
package com.java.dp.copy; /** * @Author lizhilong * @create 2019/12/2 15:42 * @desc */ public class CopyMain { public static void main(String[] args) throws CloneNotSupportedException { Student st1 = new Student(); st1.setName("小明"); st1.setAge(19); Subject subject = new Subject(); subject.setName("语文"); subject.setScore(88.9); st1.setSubject(subject); System.out.println("st1:"+st1.toString()); Student st2 = (Student) st1.clone(); System.out.println("st2:"+st2.toString()); subject.setName("数学"); System.out.println("------------------------------------------------"); System.out.println("修改后st1:"+st1.toString()); System.out.println("修改后st2:"+st2.toString()); } }
st1:Student(name=小明, age=19, subject=Subject(name=语文, score=88.9)) st2:Student(name=小明, age=19, subject=Subject(name=语文, score=88.9)) ------------------------------------------------ 修改后st1:Student(name=小明, age=19, subject=Subject(name=数学, score=88.9)) 修改后st2:Student(name=小明, age=19, subject=Subject(name=数学, score=88.9))
可以发现,当引用对象修改了以后,两个student对象均受到影响,无法做到只修改其中一个的值。
4.实现深克隆
package com.java.dp.copy; import lombok.Data; /** * @Author lizhilong * @create 2019/12/2 15:34 * @desc */ @Data public class Subject implements Cloneable{ private String name; private Double score; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
package com.java.dp.copy; import lombok.Data; import lombok.ToString; /** * @Author lizhilong * @create 2019/12/2 15:33 * @desc */ @Data @ToString public class Student implements Cloneable{ private String name; private Integer age ; private Subject subject; @Override public Object clone() throws CloneNotSupportedException { Student student = (Student) super.clone(); student.subject = (Subject)subject.clone(); return student; } }
package com.java.dp.copy; /** * @Author lizhilong * @create 2019/12/2 15:42 * @desc */ public class CopyMain { public static void main(String[] args) throws CloneNotSupportedException { Student st1 = new Student(); st1.setName("小明"); st1.setAge(19); Subject subject = new Subject(); subject.setName("语文"); subject.setScore(88.9); st1.setSubject(subject); System.out.println("st1:"+st1.toString()); Student st2 = (Student) st1.clone(); System.out.println("st2:"+st2.toString()); subject.setName("数学"); System.out.println("------------------------------------------------"); System.out.println("修改后st1:"+st1.toString()); System.out.println("修改后st2:"+st2.toString()); } }
st1:Student(name=小明, age=19, subject=Subject(name=语文, score=88.9)) st2:Student(name=小明, age=19, subject=Subject(name=语文, score=88.9)) ------------------------------------------------ 修改后st1:Student(name=小明, age=19, subject=Subject(name=数学, score=88.9)) 修改后st2:Student(name=小明, age=19, subject=Subject(name=语文, score=88.9))
可以看到,修改了subject的name属性后,只有st1 受到影响,st2 没有受到影响,因为它的引用对象属性也是新对象。