原型模式

原型模式

原型模式主要涉及對象的拷貝。之前針對Python語言寫過一篇比較詳細的關於對象賦值、淺拷貝、深拷貝的博客:python對象賦值、淺複製、深複製的區別. 下面就主要寫一下淺拷貝和深拷貝在Java語言中的實現。

Java淺拷貝

Java的淺拷貝通過實現Cloneable接口並重寫clone方法來實現,本質上是調用了Object類的clone方法由JNI實現了具體類的淺拷貝,用戶無需關心其細節。以下是Person類的淺拷貝的實例代碼。
驅動類:Main.java

package shallow_clone;

public class Main {
    public static void main(String[] args) {
        Person me = new Person(1, "da_kao_la");
        try {
            Person you = me.clone();
            me.setId(2);
            System.out.println(me);             // id: 2, name: da_kao_la
            System.out.println(you);            // id: 1, name: da_kao_la
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

Person.java

package shallow_clone;

public class Person implements Cloneable {
    private int id;
    private String name;

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    @Override
    public String toString() {
        return "id: " + id + ", name: " + name;
    }
}

Java深拷貝

Java的深拷貝有兩種方法:

  1. 當類屬性的引用關係層數不深時,Java的深拷貝可以通過遞歸調用clone方法實現
  2. 利用對象序列化機制的拷貝是一種通用的深拷貝方法,對於任何用戶編寫的類,其深拷貝方法的代碼是固定的

以下演示利用對象序列化機制的深拷貝。
驅動類:Main.java,比較了淺拷貝和深拷貝的差異。

package deep_clone;

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person(1, "da_kao_la");
        Person p2 = new Person(2, "java");
        Person p3 = new Person(3, "cpp");
        p1.addFriend(p2);
        try {
            /********** shallow clone **********/
            Person p0 = p1.clone();
            p0.addFriend(p3);
            System.out.println(p1);         
            // id: 1
            // name: da_kao_la
            // friends: 
            //     id: 2, name: java
            //     id: 3, name: cpp
            System.out.println(p0);
            // id: 1
            // name: da_kao_la
            // friends: 
            //     id: 2, name: java
            //     id: 3, name: cpp
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        /********** deep clone **********/
        p1 = new Person(1, "da_kao_la");
        p1.addFriend(p2);
        Person p0 = p1.deepClone();
        p0.addFriend(p3);
        System.out.println(p1);         
        // id: 1
        // name: da_kao_la
        // friends: 
        //         id: 2, name: java
        System.out.println(p0);
        // id: 1
        // name: da_kao_la
        // friends: 
        //         id: 2, name: java
        //         id: 3, name: cpp
    }
}

Person.java,其clone方法和deepClone方法分別實現了對象的淺拷貝和深拷貝。

package deep_clone;

import java.io.Serializable;
import java.util.ArrayList;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Person implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private ArrayList<Person> friends;

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void addFriend(Person friend) {
        this.friends.add(friend);
    }

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
        this.friends = new ArrayList<>();
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    public Person deepClone() {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Person) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("id: " + this.id + "\n");
        sb.append("name: " + this.name + "\n");
        sb.append("friends: \n");
        for (Person friend: this.friends) {
            sb.append("\tid: " + friend.getId() + ", name: " + friend.getName() + "\n");
        }
        return sb.toString();
    }
}
發佈了715 篇原創文章 · 獲贊 141 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章