设计模式-原型模式实例-02-深克隆
设计模式-原型模式实例-深克隆
浅克隆与深克隆:
浅克隆:
当对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量未被复制。(Object.clone()方法)
深克隆:
对象本身及其包含的所有成员变量也将被复制。
(序列化,通过序列化对象将对象写到一个流中,再从流中读出来。原型必须实现Serializable接口(空接口/标识接口),才能序列化。)
注意:
x.clone() != x; //克隆对象和原型并非同一对象。
x.clone().getClass() == x.getClass(); //克隆对象与原对象类型一样。
如果equals()定义恰当,x.clone().equals(x);
要点:
当需要创建大量相同或相似对象时,可通过对一个已有对象的复制获取更多的对象(克隆/复制)。
通过克隆方法所创建的对象是全新的对象,拥有新的内存地址,是独立的。
优点:
简化对象创建过程,提高创建效率;
扩展性好;
简化创建结构,无须专门的工厂类;
可使用深克隆,保存对象状态,以便在需要的时候使用,可辅助实现撤销操作。
缺点:
每一个类需要一个克隆方法,对已有类改造时需修改源代码,违背开闭原则;
深克隆需编写一个较为复杂的代码。
适用环境:
创建新对象成本较大;
系统要保存对象的状态,而对象的状态变化很小;
避免使用分层次的工厂类创建分层次的对象。
类图
代码实现:
代码结构:
Email.java:
import java.io.*; //具体原型类 public class Email implements Serializable { private Attachment attachment = null; public Email(){ this.attachment = new PrototypePattern.Attachment(); } public Object deepClone() throws IOException,ClassNotFoundException, OptionalDataException{ //将对象写入流中 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(this); //将对象从流中取出 ByteArrayInputStream bis = new ByteArrayInputStream((bao.toByteArray())); ObjectInputStream ois = new ObjectInputStream(bis); return(ois.readObject()); } public Attachment getAttachment(){ return this.attachment; } public void display(){ System.out.println("read the email"); } }
Attachment.java:
import java.io.Serializable; //附件类 public class Attachment implements Serializable { public void download(){ System.out.println("download the fuemail"); } }
Client.java:
public class Client { public static void main(String[] args) { Email email,copyEmail = null; email = new Email(); try { copyEmail = (Email) email.deepClone(); }catch (Exception e){ e.printStackTrace(); } System.out.println("email == copyEmail?"); System.out.println(email == copyEmail); System.out.println("email.getAttachment == copyEmail.getAttachment?"); System.out.println(email.getAttachment() == copyEmail.getAttachment()); } }
结论:
深克隆通过写入流和写出流(Serializable),将其成员变量也克隆了一份。