原型模式精講
原型模式是一種建立型模式,也是屬於建立物件的一種方式,像西遊記裡面的孫悟空吹猴毛也屬於原型模式,克隆出來了一群的猴子猴孫,還有細胞的分裂,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); } }
這種方式比較簡單,不用寫很多的冗餘的程式碼,有利於程式碼的閱讀。