原型模式精講
阿新 • • 發佈:2018-10-04
zab ado 序列 拷貝 sta args write 官方 stat
原型模式是一種創建型模式,也是屬於創建對象的一種方式,像西遊記裏面的孫悟空吹猴毛也屬於原型模式,克隆出來了一群的猴子猴孫,還有細胞的分裂,spring中的Bean的生命周期好像有一個單例還有個原型,那個原型就是每次請求都復制一個對象出來,官方的定義是:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。在java裏面有一個clone的方法是屬於Object類的,java裏的克隆有淺克隆和深克隆之分,下面通過代碼來看看:
淺克隆
package pattern.prototype; public class Person implements Cloneable { publicString 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); } }
這種方式比較簡單,不用寫很多的冗余的代碼,有利於代碼的閱讀。
原型模式精講