原始模型模式属于对象的创建模式。通过给出一个原始对象来致命所要创建的对象的类型,然后用复制这个原始对象的办法来创建出更多同类型的对象。
从孙大圣的手段谈起:悟空可以用猴毛根据自己的形象,复制出很多“身外之身”来。老孙的这种手段在面向对象的设计领域里叫做原始模型模式。
下面看一下,实现大圣自我复制的浅拷贝代码实现,代码包含三个类。一个齐天大圣类,其中包含一个本尊对象Monkey。还有一个Monkey类,用来定义悟空。还有一个金箍棒类,定义金箍棒。
import java.util.Date; /* * Monkey类,定义猴子 * */ public class Monkey implements Cloneable { private int height; private int weight; private GoldRingedStaff staff; private Date birthDate; public Monkey() { this.birthDate=new Date();
this.staff=new GoldRingedStaff(); } /* * 克隆方法 * */ public Object clone() { Monkey temp=null; try { temp=(Monkey)super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block System.err.println("clone failed"); } return temp; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public GoldRingedStaff getStaff() { return staff; } public void setStaff(GoldRingedStaff staff) { this.staff = staff; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } }
* * 金箍棒类源代码 * */ public class GoldRingedStaff { private float height=100.0F; private float diameter=10.0F; public GoldRingedStaff() { //write you code here } /* * 增长行为,每次调用长度和半径增加一倍 * */ public void grow() { this.diameter*=2.0; this.height*=2.0; } /* * 缩小行为,每次调用长度和半径减少一半 * */ public void shrink() { this.diameter/=2.0; this.height/=2.0; } /* * 移动方法 * */ public void move() { } public float getHeight() { return height; } public void setHeight(float height) { this.height = height; } public float getDiameter() { return diameter; } public void setDiameter(float diameter) { this.diameter = diameter; } }
public class TheGreatestSage { //大圣本尊 private Monkey monkey=new Monkey(); public void change() { //大圣的克隆版 Monkey copyMonkey; //空转一会,模拟克隆过程 for(int i=0;i<200;i++){} //复制 copyMonkey=(Monkey)monkey.clone(); System.out.println("悟空本尊的生日:"+monkey.getBirthDate()); System.out.println("复制悟空的生日:"+copyMonkey.getBirthDate());
System.out.println("悟空本尊和复制悟空的生日是否是一个对象:"+(copyMonkey.getBirthDate()==monkey.getBirthDate())); System.out.println("悟空本尊和复制悟空是否相同:"+(monkey==copyMonkey)); System.out.println("悟空本尊和复制悟空的金箍棒是否相同:"+(monkey.getStaff()==copyMonkey.getStaff())); } public static void main(String[] args) { TheGreatestSage tgs=new TheGreatestSage(); tgs.change(); } }
运行结果: 悟空本尊的生日:Tue Aug 11 03:02:07 CST 2015 复制悟空的生日:Tue Aug 11 03:02:07 CST 2015 悟空本尊和复制悟空的生日是否是一个对象:true 悟空本尊和复制悟空是否相同:false 悟空本尊和复制悟空的金箍棒是否相同:true
从运行结果可以看出,复制的悟空确实和大圣不是一个对象,他们具有同一个生日,金箍棒也是共享的,只有一个,因此浅拷贝不符合要求。需要用深拷贝来完成大圣的复制。
下面是深拷贝的实现,用序列化的方式实现深拷贝,则需要拷贝的类均需要实现Serializable接口,代码主要修改是给GoldRingedStaff实现Serializable接口,以及Monkey类也实现该接口同时添加deepCpoy()方法
/* * 金箍棒类源代码 * */ public class GoldRingedStaff implements Serializable{ private float height=100.0F; private float diameter=10.0F; public GoldRingedStaff() { //write you code here } /* * 增长行为,每次调用长度和半径增加一倍 * */ public void grow() { this.diameter*=2.0; this.height*=2.0; } /* * 缩小行为,每次调用长度和半径减少一半 * */ public void shrink() { this.diameter/=2.0; this.height/=2.0; } /* * 移动方法 * */ public void move() { } public float getHeight() { return height; } public void setHeight(float height) { this.height = height; } public float getDiameter() { return diameter; } public void setDiameter(float diameter) { this.diameter = diameter; } }
/* * Monkey类,定义猴子 * */ public class Monkey implements Cloneable,Serializable { private int height; private int weight; private GoldRingedStaff staff; private Date birthDate; public Monkey() { this.birthDate=new Date(); this.staff=new GoldRingedStaff(); } /* * 深拷贝方法 * */ public Object deepClone() throws IOException, ClassNotFoundException { //将对象写到流里 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(); } /* * 克隆方法 * */ public Object clone() { Monkey temp=null; try { temp=(Monkey)super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block System.err.println("clone failed"); } return temp; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public GoldRingedStaff getStaff() { return staff; } public void setStaff(GoldRingedStaff staff) { this.staff = staff; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } }
运行结果: 悟空本尊的生日:Tue Aug 11 03:06:09 CST 2015 复制悟空的生日:Tue Aug 11 03:06:09 CST 2015 悟空本尊和复制悟空的生日是否是一个对象:false 悟空本尊和复制悟空是否相同:false 悟空本尊和复制悟空的金箍棒是否相同:false
从运行结果来看,大圣的金箍棒和身外之身的金箍棒也是不同的对象了,这是深拷贝的效果
原文:http://www.cnblogs.com/xtsylc/p/4719793.html