原型模式是一種創建型設計模式,它通過複製一個已經存在的實例來返回新的實例,而不是新建實例.被複制的實例就是我們所稱的原型,這個原型是可定製的.
原型模式多用於創建複雜的或者耗時的實例, 因爲這種情況下,複製一個已經存在的實例可以使程序運行更高效,或者創建值相等,只是命名不一樣的同類數據.
原型模式中的拷貝分爲"淺拷貝"和"深拷貝":
淺拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量只複製引用,不復制引用的對象.
深拷貝: 對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製.
類圖:
下面我們用克隆羊的例子來示例
package com.iter.devbox.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;
import java.text.SimpleDateFormat;
import java.util.Date;
// 克隆
public class Sheep implements Cloneable,Serializable {
private String sname;
private Date birthday;
//利用系統的克隆方法實現克隆對象
protected Object clone() throws CloneNotSupportedException {
Sheep s = (Sheep) super.clone();
// 添加下面代碼實現深拷貝。即把成員變量爲對象的進行拷貝
s.birthday = (Date) this.birthday.clone();
return s;
}
/**
* 利用串行化來做深複製
* 把對象寫到流裏的過程是串行化(Serilization)過程;
* 把對象從流中讀出來是並行化(Deserialization)過程.
* 寫在流裏的是對象的一個拷貝,然後再從流裏讀出來重建對象.
*/
public Object deepClone() {
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return oi.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
public String toString() {
return this.sname + ": " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(birthday);
}
public Sheep(String sname, Date birthday) {
super();
this.sname = sname;
this.birthday = birthday;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
package com.iter.devbox.prototype;
import java.util.Calendar;
import java.util.Date;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Calendar calendar = Calendar.getInstance();
calendar.set(1010, 3, 21, 7, 34, 43);
Date date = new Date(calendar.getTimeInMillis());
Sheep s1 = new Sheep("111羊",date);
Sheep s2 = (Sheep) s1.clone();
Sheep s3 = (Sheep) s1.deepClone();
s2.setSname("222羊");
s3.setSname("333羊");
System.out.println("改變date之前s1的值==" + s1.toString());
System.out.println("改變date之前s2的值==" + s2.toString());
System.out.println("改變date之前s3的值==" + s3.toString() + "\n");
calendar.set(2120, 4, 22, 8, 35, 44);
date.setTime(calendar.getTimeInMillis());
System.out.println("改變date之後s1的值==" + s1.toString());
System.out.println("改變date之後s2的值==" + s2.toString());
System.out.println("改變date之後s3的值==" + s3.toString());
}
}
運行結果:
改變date之前s1的值==111羊: 1010-04-21 07:34:43
改變date之前s2的值==222羊: 1010-04-21 07:34:43
改變date之前s3的值==333羊: 1010-04-21 07:34:43
改變date之後s1的值==111羊: 2120-05-22 08:35:44
改變date之後s2的值==222羊: 1010-04-21 07:34:43
改變date之後s3的值==333羊: 1010-04-21 07:34:43