原型模式
原型模式是一种创建型模式,也是属于创建对象的一种方式,像西游记里面的孙悟空吹猴毛也属于原型模式,克隆出来了一群的猴子猴孙,还有细胞的分裂,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; } @Override public 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; } @Override public 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); } }
这种方式比较简单,不用写很多的冗余的代码,有利于代码的阅读。