赞
踩
原型模式用于创建重复对象并且保证性能,它属于是一种创建型的设计模式,提供了一种创建对象的最佳方式。
该设计模式用于实现一个原型接口,该接口用于创建当前对象的克隆对象。
应用实例场景: 可以想象成细胞分裂、克隆羊多利、孙悟空拔一根猴毛,吹出千万个。
首先我们有一个要被克隆的原始 羊 这个类如下:
- public class Sheep implements Cloneable{
-
- private String name;
-
- private int age;
- //表示羊腿
- public Leg leg;
-
- public ArrayList<String>strs = new ArrayList<String>(); //set get 方法省略,这个时候这个Sheep类中的clone方法中没有进行任何特殊操作
- }
- //羊腿类
- public class Leg {
-
- private String leglong;
- private String legweight;
- public String getLeglong() {
- return leglong;
- }
- public void setLeglong(String leglong) {
- this.leglong = leglong;
- }
- public String getLegweight() {
- return legweight;
- }
- public void setLegweight(String legweight) {
- this.legweight = legweight;
- }
-
- }
接下来写一个测试类进行克隆操作:
- public class CloneCellTest {
-
- public static void main(String[] args) {
-
- Sheep cell1 = new Sheep();
-
- cell1.setName("普通绵羊");
-
- cell1.setAge(11);
-
-
- Leg l = new Leg(); l.setLeglong("120"); l.setLegweight("10");
- cell1.setLeg(l);
-
- ArrayList<String>list = new ArrayList();
- list.add("母羊");
- list.add("白色");
- list.add("40kg");
-
-
- cell1.setStrs(list);
-
- try {
- Sheep cell1clone = (Sheep) cell1.clone();
-
-
- System.out.println(cell1clone.getName());
- System.out.println(cell1clone.getAge());
- System.out.println(cell1clone.strs.size());
-
- System.out.println( cell1.strs == cell1clone.strs );
- System.out.println( cell1.leg == cell1clone.leg );
-
- } catch (CloneNotSupportedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
- }
执行 CloneCellTest的main方法,得到的结果如下:
注意到 这里 cell1.strs == cell1clone.strs , cell1.leg == cell1clone.leg
代表的是 被克隆的对象和克隆出来的对象 其 对象中的引用对象 Leg 和 List<String>strs , 其指向的是同一地址,这样子的克隆被称之为 浅克隆,
浅克隆只克隆对象中的基本数据类型,包括 byte、short、int、long、float、double、boolean、char、String (八种基本数据类型和一个引用类型),
而对象中的其他非String引用对象类型则不会被克隆,如本例子中 Sheep 中的leg 和 List<String>strs
在实际开发中,更经常使用到的是深克隆,即对象中的对象也被克隆出来
接下来对程序进行一些改造:
Sheep 类中的clone方法重写成这样的
- @Override
- protected Object clone() throws CloneNotSupportedException {
- // TODO Auto-generated method stub
-
- Sheep sheepClone = null;
- if(sheepClone==null){
-
- sheepClone = (Sheep) super.clone();
- sheepClone.strs = (ArrayList<String>)(this.strs.clone());
-
- }
- return sheepClone;
- //return super.clone();
-
- }
注意到 Sheep类的clone方法中调用了 ArrayList 的 clone 方法,所以说,当 Sheep 对象进行克隆后的产生的克隆对象 和 原始sheep中的 strs 不再指向同一个地址,自此,完成了部分深克隆。
但是有的时候我们的对象中的对象 如果不是那么方便的访问其属性,不能够对其clone方法进行改写的时候,这个时候应该使用字节流加上序列化的方法完成对对象的深克隆。
这个时候 Sheep 和 Leg 两个类都要实现 Serilizable 接口,以便序列化,代码如下:
Sheep类:
- public class Sheep implements Cloneable,Serializable{
-
- private String name;
-
- private int age;
- //表示羊腿
- public Leg leg;
-
- public ArrayList<String>strs = new ArrayList<String>(); //set 和 get 方法省略
........................................
- @Override
- protected Object clone() throws CloneNotSupportedException {
- // TODO Auto-generated method stub
-
- ByteArrayOutputStream bos = null ;
- ObjectOutputStream oos = null ;
- ByteArrayInputStream bis = null ;
- ObjectInputStream ois = null ;
- try {
- //直接super.clone() 这个是浅克隆,只克隆八大基本数据类型 return super.clone();
- //序列化
- bos = new ByteArrayOutputStream();
- oos = new ObjectOutputStream(bos);
- oos.writeObject(this);
-
-
- //反序列化
- bis = new ByteArrayInputStream( bos.toByteArray() );
- ois = new ObjectInputStream( bis );
- Sheep copy = (Sheep) ois.readObject();
-
-
- return copy;
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
- }finally{
- try {
- bos.close();
- oos.close();
- bis.close();
- ois.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- }
-
- }
- //羊腿类
- public class Leg implements Serializable{
-
- private String leglong;
- private String legweight;
- public String getLeglong() {
- return leglong;
- }
- public void setLeglong(String leglong) {
- this.leglong = leglong;
- }
- public String getLegweight() {
- return legweight;
- }
- public void setLegweight(String legweight) {
- this.legweight = legweight;
- }
-
- }
测试类:
- public class CloneCellTest {
-
- public static void main(String[] args) {
-
- Sheep cell1 = new Sheep();
-
- cell1.setName("普通绵羊");
-
- cell1.setAge(11);
-
-
- Leg l = new Leg(); l.setLeglong("120"); l.setLegweight("10");
- cell1.setLeg(l);
-
- ArrayList<String>list = new ArrayList();
- list.add("母羊");
- list.add("白色");
- list.add("40kg");
-
-
- cell1.setStrs(list);
-
- try {
- Sheep cell1clone = (Sheep) cell1.clone();
-
-
- System.out.println(cell1clone.getName());
- System.out.println(cell1clone.getAge());
- System.out.println(cell1clone.strs.size());
-
- System.out.println( cell1.strs == cell1clone.strs );
- System.out.println( cell1.leg == cell1clone.leg );
-
- } catch (CloneNotSupportedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
- }
看到 输出的 克隆和 被克隆对象里面的引用 两个地址是不同的,至此完成 深度克隆。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。