原型模式的核心是如何实现拷贝
public class PrototypeClass implements Cloneable { public PrototypeClass clone() { PrototypeClass prototypeClass = null; try { prototypeClass = (PrototypeClass) super.clone(); } catch (CloneNotSupportedException exception) { exception.printStackTrace(); } return prototypeClass; } }
package com.lzhsite.technology.deepcopy; /** * 浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。 * 深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。举例来说更加清楚:对象A1中包含对B1的引用, * B1中包含对C1的引用。浅拷贝A1得到A2,A2 中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归, * 深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2 中包含对C2(C1的copy)的引用。 * 若不对clone()方法进行改写,则调用此方法得到的对象即为浅拷贝,下面我们着重谈一下深拷贝 * * 注意:深复制只针自定义对象,基本数据类型的对象默认都是深复制 */ class Professor0 implements Cloneable { String name; int age; Professor0(String name, int age) { this.name = name; this.age = age; } public Object clone() throws CloneNotSupportedException { return super.clone(); } } class Student0 implements Cloneable { String name;// 常量对象。 int age; Professor0 p;// 学生1和学生2的引用值都是一样的。 Student0(String name, int age, Professor0 p) { this.name = name; this.age = age; this.p = p; } public Object clone() { Student0 o = null; try { o = (Student0) super.clone(); } catch (CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } public class ShallowCopy { public static void main(String[] args) { Professor0 p = new Professor0("wangwu", 50); Student0 s1 = new Student0("zhangsan", 18, p); Student0 s2 = (Student0) s1.clone(); s2.p.name = "lisi"; s2.p.age = 30; s2.name = "z"; s2.age = 45; System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age);// 学生1的教授 } }
预想输出: 学生s1的姓名:zhangsan 学生s1教授的姓名:wangwu, 学生s1教授的年纪50 结果输出: 学生s1的姓名:zhangsan 学生s1教授的姓名:lisi, 学生s1教授的年纪30
下面来通过一个实例来理解下深浅拷贝:
public class Client { public static void main(String args []) throws CloneNotSupportedException { DogClone dogClone = new DogClone(); dogClone.legCounts = 3; System.out.println("原来的克隆狗腿数量:"+dogClone.legCounts); System.out.println("原来的普通狗腿的数量:"+dogClone.dog);//Dog的toString方法返回的值。 DogClone dogClone1 = (DogClone)dogClone.clone(); dogClone1.legCounts=2 ; Dog dog = dogClone1.dog; dog.changeLegCounts(); System.out.println("克隆后原来狗腿数量:"+dogClone.legCounts); /** * 出现的结果是:8 * 原因很简单就是dog是一个引用,改变一个对象的话,会改变另一个对象。 */ System.out.println("克隆后原来普通狗的数量:"+ dogClone.dog); System.out.println("克隆后克隆狗腿的数量:"+ dogClone1.legCounts); /** *改变源:改变了自身dogClone.dog,影像了对象dogClone.dog 的值, */ System.out.println("克隆后普通狗的数量:"+ dogClone1.dog); } }
/** * 未实现了克隆方法的类和实现克隆方法的类做比较 * */ public class Dog { /** * 狗腿条数 */ public int legCounts; public Dog(int legCounts) { this.legCounts = legCounts; } /** * 改变狗的腿数量 */ public void changeLegCounts(){ this.legCounts *=2; } public String toString () { return Integer.toString(this.legCounts); } }
public class DogClone implements Cloneable { /** * 狗腿条数 */ public int legCounts; /** * 初始化一个狗 */ Dog dog = new Dog(4); @Override protected DogClone clone() throws CloneNotSupportedException { return (DogClone)super.clone(); } }
输出结果:
原来的克隆狗腿数量:3
原来的普通狗腿的数量:4
克隆后原来狗腿数量:3
克隆后原来普通狗的数量:8
克隆后克隆狗腿的数量:2
克隆后普通狗的数量:8
让Doc实现Cloneable接口后
/** * 该类是没有实现克隆方法的类和实现克隆方法的类做比较 * */ public class Dog implements Cloneable{ /** * 狗腿条数 */ public int legCounts; public Dog(int legCounts) { this.legCounts = legCounts; } /** * 改变狗的腿数量 */ public void changeLegCounts(){ this.legCounts *=2; } @Override public Dog clone() throws CloneNotSupportedException { return (Dog)super.clone(); } public String toString () { return Integer.toString(this.legCounts); } }
输出结果:
原来的克隆狗腿数量:3
原来的普通狗腿的数量:4
克隆后原来狗腿数量:3
克隆后原来普通狗的数量:4
克隆后克隆狗腿的数量:2
克隆后普通狗的数量:8
对原型模式的总结: