原型模式是一种创建型模式,也是属于创建对象的一种方式,像西游记里面的孙悟空吹猴毛也属于原型模式,克隆出来了一群的猴子猴孙,还有细胞的分裂,spring中的Bean的生命周期好像有一个单例还有个原型,那个原型就是每次请求都复制一个对象出来,官方的定义是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。在java里面有一个clone的方法是属于Object类的,java里的克隆有浅克隆和深克隆之分,下面通过代码来看看:
浅克隆
package pattern.prototype; public class Person implements Cloneable {public String name;public String pass;public String[] arr;public Person(String name,String pass,String[] arr){this.name=name;this.pass=pass;this.arr=arr;}@Overridepublic Object clone() throws CloneNotSupportedException {Person person=(Person)super.clone();return person;} }
package pattern.prototype;public class Test {public static void main(String[] args) throws CloneNotSupportedException {String[] arr={"hello1","hello2"};Person person=new Person("zj","123",arr);Person p=(Person)person.clone();System.out.println(p.name);System.out.println(p.pass);p.name="jack";p.pass="666";p.arr[0]="wahaha";for (String favor : p.arr) {System.out.print(favor + " ");}System.out.println();for (String favor : person.arr) {System.out.print(favor + " ");}System.out.println();} }
返回结果:
zj 123 wahaha hello2 wahaha hello2
通过上面可以看出来,p中的arr修改了值以后,person中的值也进行了修改,所以这是属于浅克隆,浅克隆,对于被克隆的类中成员变量都是基本数据类型,可以实现了两份数据;被克隆的类中成员变量是对象类型,那么这个成员变量还是原来的引用,修改为新对象的值,旧对象的该对象类型的成员变量还是会变化。
深克隆
package pattern.prototype; public class Person implements Cloneable {public String name;public String pass;public String[] arr;public Person(String name,String pass,String[] arr){this.name=name;this.pass=pass;this.arr=arr;}@Overridepublic Object clone() throws CloneNotSupportedException {Person person=(Person)super.clone();person.arr=arr.clone();return person;} }
package pattern.prototype;public class Test {public static void main(String[] args) throws CloneNotSupportedException {String[] arr={"hello1","hello2"};Person person=new Person("zj","123",arr);Person p=(Person)person.clone();System.out.println(p.name);System.out.println(p.pass);p.name="jack";p.pass="666";p.arr[0]="wahaha";for (String favor : p.arr) {System.out.print(favor + " ");}System.out.println();for (String favor : person.arr) {System.out.print(favor + " ");}System.out.println();} }
返回结果:
zj 123 wahaha hello2 hello1 hello2
数组中的两个值的修改是都不会影响的,因为他们属于两个对象,所以上面的是属于深克隆.从新生成了地址。但是重写clone方法实现深克隆比较麻烦,要对所有是对象类型的成员变量,进行重新创建实例,重新赋值; 集合类会更麻烦,比如说ArrayList虽然重写了clone(),但还是浅克隆,实现深克隆需要遍历所有的model,创建实例,重新赋值的。
序列化实现深克隆
package pattern.prototype; import java.io.*;public class Apple implements,Serializable {public String name;public int age;public Apple(String name,int age){this.name=name;this.age=age;}public Object deepClone(Object obj) {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = null;ObjectInputStream ois = null;try {oos = new ObjectOutputStream(bos);oos.writeObject(obj);ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));return ois.readObject();} catch (Exception e) {e.printStackTrace();} finally {try {bos.close();oos.close();ois.close();} catch (Exception e) {e.printStackTrace();}}return null;}public static void main(String[] args) {Apple apple=new Apple("aaa",18);Apple apple1 = (Apple) apple.deepClone(apple);System.out.println(apple1==apple);} }
这种方式比较简单,不用写很多的冗余的代码,有利于代码的阅读。