深入理解Java設計模式-原型模式

什麼是原型模式

原型設計模式簡單來說就是克隆

原型表明了有一個樣板實例,這個原型是可定製的。原型模式多用於創建複雜的或者構造耗時的實例,因爲這種情況下,複製一個已經存在的實例可使程序運行更高效。

原型模式的應用場景

  1. 類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。這時我們就可以通過原型拷貝避免這些消耗。
  2. 通過new產生的一個對象需要非常繁瑣的數據準備或者權限,這時可以使用原型模式。
  3. 一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用,即保護性拷貝。

我們Spring框架中的多例就是使用原型。

原型模式的使用方式

  1. 實現Cloneable接口。在java語言有一個Cloneable接口,它的作用只有一個,就是在運行時通知虛擬機可以安全地在實現了此接口的類上使用clone方法。在java虛擬機中,只有實現了這個接口的類纔可以被拷貝,否則在運行時會拋出CloneNotSupportedException異常。

  2. 重寫Object類中的clone方法。Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回對象的一個拷貝,但是其作用域protected類型的,一般的類無法調用,因此Prototype類需要將clone方法的作用域修改爲public類型。

原型模式分爲淺複製和深複製

  1. (淺複製)只是拷貝了基本類型的數據,而引用類型數據,只是拷貝了一份引用地址。

  2. (深複製)在計算機中開闢了一塊新的內存地址用於存放複製的對象。

代碼演示

  1. 創建User類
package com.lijie;

import java.util.ArrayList;

public class User implements Cloneable {
    private String name;
    private String password;
    private ArrayList<String> phones;

    protected User clone() {
        try {
            User user = (User) super.clone();
            //重點,如果要連帶引用類型一起復制,需要添加底下一條代碼,如果不加就對於是複製了引用地址
            user.phones = (ArrayList<String>) this.phones.clone();//設置深複製
            return user;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
	
	//省略所有屬性Git Set方法......
}
  1. 測試複製
package com.lijie;

import java.util.ArrayList;

public class Client {
    public static void main(String[] args) {
        //創建User原型對象
        User user = new User();
        user.setName("李三");
        user.setPassword("123456");
        ArrayList<String> phones = new ArrayList<>();
        phones.add("17674553302");
        user.setPhones(phones);

        //copy一個user對象,並且對象的屬性
        User user2 = user.clone();
        user2.setPassword("654321");

        //查看倆個對象是否是一個
        System.out.println(user == user2);

        //查看屬性內容
        System.out.println(user.getName() + " | " + user2.getName());
        System.out.println(user.getPassword() + " | " + user2.getPassword());
        //查看對於引用類型拷貝
        System.out.println(user.getPhones() == user2.getPhones());
    }
}
  1. 如果不需要深複製,需要刪除User 中的
//默認引用類型爲淺複製,這是設置了深複製
user.phones = (ArrayList<String>) this.phones.clone();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章