淺克隆Demo:
羊:
package prototype_mode;
import java.util.Date;
/**
* 羊
* 對象要可以克隆, 需要實作空接口, 标記接口Cloneable, 這是規範
* clone是object方法, c實作, 效率極高
*/
public class Sheep implements Cloneable {
private String sname;
private Date birthday;
/**
* 覆寫父類(Object)的克隆方法, 測試淺克隆
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();//直接調用object對象的clone()方法進行克隆, 傳回克隆後的對象!
return obj;
}
public Sheep(){
}
public Sheep(String sname, Date birthday) {
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;
}
}
概念圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SYwMTN5IzMmJ2MxUmMwQjZmRWYyMTOiNzMlhDO5Q2Y18CXzAzLclDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL1M3Lc9CX6MHc0RHaiojIsJye.png)
測試類:
package prototype_mode;
import java.util.Date;
/**
* 測試原型模式, 淺克隆
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
//建立原型對象
Sheep s1 = new Sheep("少利", new Date(12312312312l));
System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
//克隆原型對象
Sheep s2 = (Sheep) s1.clone();
System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
//修改克隆對象
s2.setSname("多利"); //1997年, 英國的克隆羊, 多利!
s2.getBirthday().setTime(32132132132l);
//列印兩個對象
System.out.println("--------------------------------");
System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
//結果: 克隆對date對象隻是引用(值)克隆
}
}
列印結果:
prototype_mode.Sheep@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep@647e05: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep@1db9742: 少利, Fri Jan 08 05:35:32 CST 1971
prototype_mode.Sheep@647e05: 多利, Fri Jan 08 05:35:32 CST 1971
深克隆Demo:
羊2号:
package prototype_mode;
import java.util.Date;
/**
* 羊2号
*/
public class Sheep2 implements Cloneable { //1997年, 英國的克隆羊, 多利!
private String sname;
private Date birthday;
/**
* 覆寫父類(Object)的克隆方法, 測試深克隆
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();//直接調用object對象的clone()方法進行克隆, 傳回克隆後的對象!
//需要對Date對象也進行克隆, 如果Date對象中擁有對象, 也要一層一層的全部克隆
Sheep2 s = (Sheep2) obj;
s.birthday = (Date) this.birthday.clone();//傳回克隆後的Date!
return obj;
}
public Sheep2(){
}
public Sheep2(String sname, Date birthday) {
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 prototype_mode;
import java.util.Date;
/**
* 測試原型模式, 深克隆
*/
public class Client2 {
public static void main(String[] args) throws CloneNotSupportedException {
//建立原型對象
Sheep2 s1 = new Sheep2("少利", new Date(12312312312l));
System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
//克隆原型對象
Sheep2 s2 = (Sheep2) s1.clone();
System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
//修改克隆對象
s2.setSname("多利"); //1997年, 英國的克隆羊, 多利!
s2.getBirthday().setTime(32132132132l);
//列印兩個對象
System.out.println("--------------------------------");
System.out.println(s1 + ": " + s1.getSname() + ", " + s1.getBirthday());
System.out.println(s2 + ": " + s2.getSname() + ", " + s2.getBirthday());
//結果: 克隆對象時對Date也進行了克隆
}
}
prototype_mode.Sheep2@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep2@647e05: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep2@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep2@647e05: 多利, Fri Jan 08 05:35:32 CST 1971
以序列化形式深克隆Demo:
羊3号:
package prototype_mode;
import java.io.Serializable;
import java.util.Date;
/**
* 羊3号
* 序列化UID唯一辨別.
* 反序列化時,如果UID不一緻,就無法實作反序列化,并且将抛出InvalidClassException.[方法,域不能減,可以增,向後相容]
* 如果不顯式指定,VM預設生成一個(耗費資源),但反序列化時會出問題.
*/
public class Sheep3 implements Cloneable, Serializable {
private static final long serialVersionUID = 1218060507823188744L;
private String sname;
private Date birthday;
public Sheep3(){
}
public Sheep3(String sname, Date birthday) {
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 prototype_mode;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
/**
* 測試原型模式, 深克隆
* 使用序列化和反序列化的方式實作深複制, 待複制對象需要實作Serializable接口
*/
public class Client3 {
public static void main(String[] args) throws Exception {
//建立原型對象
Sheep3 s3 = new Sheep3("少利", new Date(12312312312l));
System.out.println(s3 + ": " + s3.getSname() + ", " + s3.getBirthday());
//使用序列化和反序列化實作深複制
//位元組流形式
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);//建立object輸出流(傳入位元組數組輸出流)
oos.writeObject(s3);//序列化羊, 包括所有持有對象也一并
byte[] bytes = bos.toByteArray();//從位元組數組輸出流中, 獲得位元組數組
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);//建立object輸入流(傳入位元組數組輸入流)
Sheep3 ss3 = (Sheep3) ois.readObject();//反序列化羊
ois.close();
System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
//檔案流形式
// ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(new File("D:\\file1")));
// oos2.writeObject(s3);
// oos2.close();
//
// ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream(new File("D:\\file1")));
// Sheep3 ss3 = (Sheep3) ois2.readObject();
// ois2.close();
// System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
//修改複制對象
ss3.setSname("多利"); //1997年, 英國的克隆羊, 多利!
ss3.getBirthday().setTime(32132132132l);
//列印兩個對象
System.out.println("--------------------------------");
System.out.println(s3 + ": " + s3.getSname() + ", " + s3.getBirthday());
System.out.println(ss3 + ": " + ss3.getSname() + ", " + ss3.getBirthday());
//結果: 序列化時, 對Date也進行了複制
}
}
prototype_mode.Sheep3@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep3@1311334: 少利, Sat May 23 20:05:12 CST 1970
--------------------------------
prototype_mode.Sheep3@1db9742: 少利, Sat May 23 20:05:12 CST 1970
prototype_mode.Sheep3@1311334: 多利, Fri Jan 08 05:35:32 CST 1971