設計模式筆記之四原型模式
阿新 • • 發佈:2018-12-19
原型模式
為什麼引入原型模式?
當我們需要建立某個物件的時候,我們使用new關鍵字,但是當我們需要建立兩個相同的物件,接著new,當數量特定少的時候,我們可以採用直接建立物件,但是當我們需要建立很多物件的時候,我們就不能一直new,首先是因為堆記憶體有限,只允許我們new特定數量的物件,因此我們需要另一種方式,快速的實現物件的複製,克隆,因此引入原型模式。
原型模式是什麼?
用原型歐例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
核心思想:
原型模式的實現方式十分簡單,即只需繼承Cloneable介面,覆蓋clone()方法。
這裡需要解釋一下什麼是淺克隆和深克隆。
淺克隆:
繼承Cloneable介面,覆蓋clone方法所實現的克隆就是淺克隆,淺克隆的方式即Object類的clone方法只是拷貝物件本身,其物件內部的陣列,引用物件都不拷貝,還是指向原生物件的內部元素地址,int,long,char等基恩型別會被拷貝,但是String型別,通過字串常量池在需要的時候才在記憶體中建立新的字串,讀者可以把String當做基本型別使用即可。
深克隆:
將物件的所有東西都拷貝一份,實現物件之間的獨立。深拷貝在淺拷貝的基礎上,對陣列,引用物件單獨拷貝。
具體案例:
我們現在有一個名牌汽車,我們希望在以這件車為模型生產很多輛
程式碼:
package com.dong.yuanxing; import java.util.ArrayList; public class Car implements Cloneable{ private String name; private int Id; private ArrayList<String> otherDes = new ArrayList<String>() ; public Car clone() { Car car =null; try { car = (Car)super.clone(); } catch (CloneNotSupportedException e) { System.out.println("克隆不支援"); return null; } return car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return Id; } public void setId(int id) { Id = id; } public ArrayList<String> getOtherDes() { return otherDes; } public void setOtherDes(String value) { this.otherDes.add(value); } } package com.dong.yuanxing; import java.util.ArrayList; //淺拷貝 public class Main { public static void main(String args[]) { Car carold ,carnew,carthre; carold = new Car(); carold.setOtherDes("111"); carnew = carold.clone(); carnew.setOtherDes("222"); System.out.println(carnew + carnew.getOtherDes().toString()); } }
深拷貝需要改動的地方:
public Car clone() { Car car =null; try { //淺拷貝 car = (Car)super.clone(); //深拷貝,即對私有的類變數進行單獨的拷貝。 //car = (Car)super.clone(); //car.otherDes = (ArrayList<String>) this.otherDes.clone(); } catch (CloneNotSupportedException e) { System.out.println("克隆不支援"); return null; } return car; } public static void main(String args[]) { Car carold ,carnew; carold = new Car(); carold.setOtherDes("111"); carnew = carold.clone(); carnew.setOtherDes("222"); System.out.println(carold + carold.getOtherDes().toString()); System.out.println(carnew + carnew.getOtherDes().toString()); }
優點
拷貝的效能優良,原型模式是在記憶體二進位制流的拷貝,要比直接new一個物件的效能好。
缺點
淺拷貝不能拷貝物件的所有,對於內部的陣列,引用物件是不會拷貝的,需要使用深拷貝。
擴充套件:
深拷貝的另一種實現方式:
package com.dong.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCloneObj implements Serializable{
private static final long serialVersionUID = 1L;
//為需要克隆的類
private StudentA student;
public StudentA getStudent() {
return student;
}
public void setStudent(StudentA student) {
this.student = student;
}
public DeepCloneObj clone() {
ByteArrayOutputStream bos;
ObjectOutputStream oos;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
try {
return (DeepCloneObj) ois.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return null;
}
}