原型模式--java代碼實現


原型模式

  原型模式,屬於對象創建型模式中的一種。通過復制原型對象的方法來創建一個對象實例,且該對象與原對象有相同的數據結構和值。類似我們在備份數據庫信息的時候,將數據庫中表的結構和數據的一同備份,生成一個數據庫文件。

  在Java環境中,要實現原型模式,要理解對象創建、引用和克隆的相關知識,在這里通過簡單分析JVM的內存在對象創建、引用和克隆時棧和堆的內容變化,來深入理解原型模式是如何在Java環境中運作的。

1.簡單理解JVM內存中棧和堆

  棧:用來存放函數中定義的基本類型的變量和對象的引用變量。

  堆:則是存放由new創建的對象和數組,對象內存儲普通的變量和方法。對象創建后將其地址賦值給棧中的引用變量。

  方法區:也是堆,這里面存放類代碼、靜態變量、靜態方法和字符串常量等。

2.引用和克隆的區別

引用的示例圖:

克隆的示意圖:

  由示例圖我們可以看出,引用,比如person2=person1,棧中兩個不同的成員變量指向對中的同一個對象,他們兩個的值是一樣的,都是該對象在內存中的地址。而克隆是將對象復制一份包括數據結構和值,將復制出的對象的地址賦值給棧中的另外一個成員變量person2。

3.淺層克隆和深層克隆

  有沒有注意到一個問題,如果普通變量是一個引用變量,比如數組,列表或map,那么克隆是否把引用變量(person1中的friends)所引用的對象也給復制一份呢。其實並沒有,只是將引用變量的變量名和值復制了一份,他們還是用的同一個引用對象,這就是淺層克隆。如淺層克隆示意圖所示。那么如果想要把引用變量所指的對象也復制一份,則需要重新新建一個對應的對象,將值傳入對象中,返回給復制后的引用變量person2中的friends中。如深層克隆示意圖所示。

淺層克隆示意圖:

深層克隆示意圖:

4.代碼實現

Person類:

  在Java中克隆該類需實現Cloneable接口,重寫了Object的 clone() 方法,該方法會創建和返回一個Person類的一個復制,也就是上述所說的淺層復制。該類中添加了淺層克隆shallowClone()和深層克隆deepClone()。

package prototype;

import java.util.ArrayList;
import java.util.List;

public class Person implements Cloneable{
    //姓名
    private String name;
    //年齡
    private int age;
    //朋友
    private List<String> friends;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public List<String> getFriends() {
        return friends;
    }
    public void setFriends(List<String> friends) {
        this.friends = friends;
    }
    //重寫toString方法
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", friends=" + friends + "]";
    }
    //淺層克隆
    public Person shallowClone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    //深層克隆
    public Person deepClone() {
        try {
            Person person = (Person) super.clone();
            List<String> newFriends = new ArrayList<String>();
            for(String friend : this.getFriends()) {
                newFriends.add(friend);
            }
            person.setFriends(newFriends);
            return person;
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

MainClass:

  通過向列表中添加值來測試淺層克隆和深層克隆。具體代碼中有注釋,請看代碼。

package prototype;

import java.util.ArrayList;
import java.util.List;

public class MainClass {
    public static void main(String[] args) {
        //創建對象person1
        Person person1 = new Person();
        //初始化對象
        person1.setName("zhangsan");
        person1.setAge(20);
        List<String> friends = new ArrayList<String>();
        friends.add("lisi");
        friends.add("wangwu");
        person1.setFriends(friends);
        //person2是淺層克隆
        Person person2 = person1.shallowClone();
        //person3是深層克隆
        Person person3 = person1.deepClone();
        //獲取淺層克隆的friends的list對象
        List<String> person2_friends = person2.getFriends();
        //向引用對象中添加值
        person2_friends.add("shallow");
        person2.setFriends(person2_friends);    
        //獲取深層克隆的friends的list對象
        List<String> person3_friends = person3.getFriends();
        //向引用對象中添加值
        person3_friends.add("deep");
        person3.setFriends(person3_friends);
        
        System.out.println("原型:"+person1);
        System.out.println("淺層克隆:"+person2);
        System.out.println("深層克隆:"+person3);
    }
}

5.結果

  從結果中可以發現,淺層克隆的person2中向friends列表中添加的shallow朋友,而在原型person1中也添加了shallow,驗證了前面的說法。深層克隆person3是在person2之前克隆的,所以沒有添加shallow朋友,而之后添加的deep朋友也沒有影響person1和person2中的friends列表。

6.總結

  通過結合JVM內存中的棧和堆來解釋原型模型,利用Java代碼成功測試。可以發現Java中默認是的克隆模式是淺層克隆,不復制引用變量所對應的對象。那么對於深層次的克隆,需要編寫對應代碼來復制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM