什麼是原型模式?
簡單來說,通過複製的方式建立物件。(被複制的物件可以理解為模板)
原型模式的應用場景
複雜結構物件的建立。
複雜結構物件:可以理解為物件裡面還有物件。
【舉個栗子】:點外賣的收貨地址
收貨地址包括姓名,電話和住址。第一次點外賣的時候需要完整的填寫這些資訊,但是之後點的過程基本上是不用再重新填寫這些資訊的。試想一下,每次下單之前都要填一遍姓名,電話,詳細地址(假設省市已經定位好了)。頭大.....而這個場景,正是原型模式的用武之地。
點外賣之前複製上一次填寫的地址,直接下單;或者手機號出現變更,修改一下直接更新到模板即可。
原型模式的本質是建立一個物件模板,然後通過複製的方式實現複用。
深拷貝(複雜物件一波帶走)
在深拷貝之前,簡單聊一下淺拷貝。
以上述收貨地址為例,如果只涉及到姓名,電話這些基本資料型別(淺拷貝與深拷貝是基本沒有區別的),但是如果涉及到地址這樣的引用型別。淺拷貝就會出現問題。淺拷貝對於引用物件,只複製其引用地址。所以複製出來的物件和被複制的物件會指向同一個值。假設你想建立兩個收貨模板,地址是不同的,那麼就只能使用深拷貝了。
擼段程式碼試試看:
思路:
1.建立Info類和Address類繼承Serializable介面,為了後面實現序列化寫入記憶體。(實現平臺無關性)
2.Info類還需要繼承Cloneable介面,並重寫clone()方法,注:protected改為public
3.在clone()方法中新增寫入記憶體和讀取的邏輯
4.Info info1 = (Info) info.clone();建立物件,並可做靈活修改。
import java.io.*;
class Address implements Serializable
{
private String province;
private String city;
private String Street;
private String door_number;
public Address(String province, String city, String street, String door_number) {
this.province = province;
this.city = city;
Street = street;
this.door_number = door_number;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return Street;
}
public void setStreet(String street) {
Street = street;
}
public String getDoor_number() {
return door_number;
}
public void setDoor_number(String door_number) {
this.door_number = door_number;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
", Street='" + Street + '\'' +
", door_number='" + door_number + '\'' +
'}';
}
}
class Info implements Cloneable, Serializable //1.建立一個外賣資訊類,繼承Cloneable(可複製),Serializable(可序列化)
{
private String name;
private String number;
Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Info(String name, String number, Address address) {
this.name = name;
this.number = number;
this.address = address;
}
@Override
public String toString() {
return "Info{" +
"name='" + name + '\'' +
", number='" + number + '\'' +
", address=" + address +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException { //2.重寫clone方法,並把protected換成public
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(this); //寫入記憶體
oos.close();
byte[] bytes = out.toByteArray();
InputStream in = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(in);
Object clone = ois.readObject(); //讀取記憶體
ois.close();
return clone;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
/*
clone()方法直接複製在記憶體中已經建立物件的二進位制,效率極高!(不需要呼叫構造器)
protected native Object clone() throws CloneNotSupportedException;
native修飾的方法直接呼叫底層的C語言
*/
public class MyInfo
{
public static void main(String[] args) throws CloneNotSupportedException {
Info info = new Info("shadow","18116207310",new Address("上海","浦東新區","振南路","355"));
System.out.println(info);
Info info1 = (Info) info.clone(); //3.複製加強轉
System.out.println(info1);
System.out.println("//修改電話:");
Info info2 = (Info) info.clone();
info2.setNumber("123456789");
System.out.println(info2);
System.out.println("//修改地址:");
Info info3 = (Info) info.clone();
info3.getAddress().setStreet("西語街");
info3.getAddress().setDoor_number("666");
System.out.println(info3);
}
}
輸出結果: