一二二、百度編碼規範--HTML
今天給大家說一下設計模式中的原型模式
何為原型模式,即以系統中有的一個物件,通過複製它的二進位制位元組流,直接來獲取到該物件,好處是在於不需要進行物件的初始化動作,因為物件的初始化還伴隨著一些函式的呼叫,比如建構函式等,在獲取效率上會提高很多
可以用在以下情況
建立該類物件需要耗費資源過大,建立過程較為複雜
這個物件系統中大量使用,且每個呼叫者都需要對該物件進行個性化操作,比如賦值等
盡然原型模式就是複製物件,那麼我們可以使用JDK中提供的API,我們可以把需要複製的類實現Java中的Cloneable介面,然後重寫object.clone()方法即可,程式碼如下
public class Prototype implements Cloneable{
private String desc;
private List<String> foods;
@Override
protected Prototype clone() {
Prototype prototype = null;//宣告一個原物件
try {
prototype=(Prototype)super.clone();//複製
} catch (Exception e) {
e.printStackTrace();
}
return prototype;
}
//省略了get、set和toString方法
}
測試程式碼
public class Test {
public static void main(String[] args) {
//建立源物件
Prototype origin=new Prototype();
origin.setDesc("食譜");
List<String> foods=new ArrayList<String>();
foods.add("火鍋");
foods.add("燒烤" );
origin.setFoods(foods);
System.out.println("原有物件"+origin);
//通過複製來建立物件
Prototype copy=origin.clone();
System.out.println("複製物件"+copy);
//那麼原物件跟複製物件有沒有關係呢?
//我們修改下複製物件內部的值
copy.setDesc("美食清單");
copy.getFoods().add("宮爆雞丁");
//再次輸出
System.out.println("原有物件"+origin);
System.out.println("複製物件"+copy);
}
}
結果如下
我們會驚訝的發現,普通變數String desc值在經過複製物件修改後,與原物件確實沒有關係了,但是List<> foods卻都發生了變化,因為List是要分配記憶體空間的,說明我們的原物件和複製物件操作了同一塊記憶體,即當存在引用資料型別時,這樣的複製只是把物件的引用複製了一份,並沒有真正的複製一塊記憶體空間給複製物件,這樣的複製叫做淺複製,也叫淺拷貝。
可是我們實現複製的本意就是讓原物件和複製物件完完全全沒有關係,那麼我們只需要在clone方法內部直接分配一塊記憶體就好了,這樣的叫做深複製,也叫深拷貝
而在Java中要實現深拷貝,我們可以用序列化的方式。我們在原有Prototype類中新新增一個方法,同時需要實現Serializable介面,其餘類內容與之前不變,程式碼如下
public class Prototype implements Cloneable,Serializable
//實現Serializable介面後再新增以下方法
public Prototype deepClone() {
try {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return (Prototype)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
再執行測試程式碼
public class Test {
public static void main(String[] args) {
//建立源物件
Prototype origin=new Prototype();
origin.setDesc("食譜");
List<String> foods=new ArrayList<String>();
foods.add("火鍋");
foods.add("燒烤");
origin.setFoods(foods);
System.out.println("原有物件"+origin);
//通過複製來建立物件
//注意,這裡呼叫的方法變了
Prototype copy=origin.deepClone();
System.out.println("複製物件"+copy);
//那麼原物件跟複製物件有沒有關係呢?我們修改下複製物件內部的值
copy.setDesc("美食清單");
copy.getFoods().add("宮爆雞丁");
//再次輸出
System.out.println("原有物件"+origin);
System.out.println("複製物件"+copy);
}
}
檢視結果
可以看到我們成功的進行了深拷貝,即複製出來了兩個完全不同的物件。
原型模式比較簡單,主要是得理解原型模式的意義,以及在複製過程中的深拷貝和淺拷貝的問題,像我們在Spring中建立Bean的時候就有單例模式和原型模式,當我們知道了這兩種模式的區別之後,就能在以後的學習和應用中得心應手。
希望今天的文章能給大家帶來一定的收穫。