1. 程式人生 > >原型模式精講

原型模式精講

zab ado 序列 拷貝 sta args write 官方 stat

原型模式是一種創建型模式,也是屬於創建對象的一種方式,像西遊記裏面的孫悟空吹猴毛也屬於原型模式,克隆出來了一群的猴子猴孫,還有細胞的分裂,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);
    }
}

這種方式比較簡單,不用寫很多的冗余的代碼,有利於代碼的閱讀。

原型模式精講