当前位置:   article > 正文

原型设计模式(浅克隆和深克隆)_基于原型模式设计深浅克隆

基于原型模式设计深浅克隆

原型模式用于创建重复对象并且保证性能,它属于是一种创建型的设计模式,提供了一种创建对象的最佳方式。


该设计模式用于实现一个原型接口,该接口用于创建当前对象的克隆对象。


应用实例场景:  可以想象成细胞分裂、克隆羊多利、孙悟空拔一根猴毛,吹出千万个。



首先我们有一个要被克隆的原始 羊 这个类如下:

  1. public class Sheep implements Cloneable{
  2. private String name;
  3. private int age;
  4. //表示羊腿
  5. public Leg leg;
  6. public ArrayList<String>strs = new ArrayList<String>(); //set get 方法省略,这个时候这个Sheep类中的clone方法中没有进行任何特殊操作
  7. }

羊腿类:

  1. //羊腿类
  2. public class Leg {
  3. private String leglong;
  4. private String legweight;
  5. public String getLeglong() {
  6. return leglong;
  7. }
  8. public void setLeglong(String leglong) {
  9. this.leglong = leglong;
  10. }
  11. public String getLegweight() {
  12. return legweight;
  13. }
  14. public void setLegweight(String legweight) {
  15. this.legweight = legweight;
  16. }
  17. }


接下来写一个测试类进行克隆操作:

  1. public class CloneCellTest {
  2. public static void main(String[] args) {
  3. Sheep cell1 = new Sheep();
  4. cell1.setName("普通绵羊");
  5. cell1.setAge(11);
  6. Leg l = new Leg(); l.setLeglong("120"); l.setLegweight("10");
  7. cell1.setLeg(l);
  8. ArrayList<String>list = new ArrayList();
  9. list.add("母羊");
  10. list.add("白色");
  11. list.add("40kg");
  12. cell1.setStrs(list);
  13. try {
  14. Sheep cell1clone = (Sheep) cell1.clone();
  15. System.out.println(cell1clone.getName());
  16. System.out.println(cell1clone.getAge());
  17. System.out.println(cell1clone.strs.size());
  18. System.out.println( cell1.strs == cell1clone.strs );
  19. System.out.println( cell1.leg == cell1clone.leg );
  20. } catch (CloneNotSupportedException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. }
  24. }
  25. }


执行  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方法重写成这样的

  1. @Override
  2. protected Object clone() throws CloneNotSupportedException {
  3. // TODO Auto-generated method stub
  4. Sheep sheepClone = null;
  5. if(sheepClone==null){
  6. sheepClone = (Sheep) super.clone();
  7. sheepClone.strs = (ArrayList<String>)(this.strs.clone());
  8. }
  9. return sheepClone;
  10. //return super.clone();
  11. }


然后再次调用  CloneCellTest的main方法,得到结果如下:




注意到 Sheep类的clone方法中调用了 ArrayList 的 clone 方法,所以说,当 Sheep 对象进行克隆后的产生的克隆对象 和 原始sheep中的 strs 不再指向同一个地址,自此,完成了部分深克隆。

但是有的时候我们的对象中的对象 如果不是那么方便的访问其属性,不能够对其clone方法进行改写的时候,这个时候应该使用字节流加上序列化的方法完成对对象的深克隆。


这个时候  Sheep 和 Leg 两个类都要实现  Serilizable  接口,以便序列化,代码如下:

Sheep类:

  1. public class Sheep implements Cloneable,Serializable{
  2. private String name;
  3. private int age;
  4. //表示羊腿
  5. public Leg leg;
  6. public ArrayList<String>strs = new ArrayList<String>(); //set 和 get 方法省略
       ........................................
  1. @Override
  2. protected Object clone() throws CloneNotSupportedException {
  3. // TODO Auto-generated method stub
  4. ByteArrayOutputStream bos = null ;
  5. ObjectOutputStream oos = null ;
  6. ByteArrayInputStream bis = null ;
  7. ObjectInputStream ois = null ;
  8. try {
  9. //直接super.clone() 这个是浅克隆,只克隆八大基本数据类型 return super.clone();
  10. //序列化
  11. bos = new ByteArrayOutputStream();
  12. oos = new ObjectOutputStream(bos);
  13. oos.writeObject(this);
  14. //反序列化
  15. bis = new ByteArrayInputStream( bos.toByteArray() );
  16. ois = new ObjectInputStream( bis );
  17. Sheep copy = (Sheep) ois.readObject();
  18. return copy;
  19. } catch (Exception e) {
  20. // TODO Auto-generated catch block
  21. e.printStackTrace();
  22. return null;
  23. }finally{
  24. try {
  25. bos.close();
  26. oos.close();
  27. bis.close();
  28. ois.close();
  29. } catch (IOException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. }
  33. }
  34. }
  35. }



Leg类:

  1. //羊腿类
  2. public class Leg implements Serializable{
  3. private String leglong;
  4. private String legweight;
  5. public String getLeglong() {
  6. return leglong;
  7. }
  8. public void setLeglong(String leglong) {
  9. this.leglong = leglong;
  10. }
  11. public String getLegweight() {
  12. return legweight;
  13. }
  14. public void setLegweight(String legweight) {
  15. this.legweight = legweight;
  16. }
  17. }


测试类:

  1. public class CloneCellTest {
  2. public static void main(String[] args) {
  3. Sheep cell1 = new Sheep();
  4. cell1.setName("普通绵羊");
  5. cell1.setAge(11);
  6. Leg l = new Leg(); l.setLeglong("120"); l.setLegweight("10");
  7. cell1.setLeg(l);
  8. ArrayList<String>list = new ArrayList();
  9. list.add("母羊");
  10. list.add("白色");
  11. list.add("40kg");
  12. cell1.setStrs(list);
  13. try {
  14. Sheep cell1clone = (Sheep) cell1.clone();
  15. System.out.println(cell1clone.getName());
  16. System.out.println(cell1clone.getAge());
  17. System.out.println(cell1clone.strs.size());
  18. System.out.println( cell1.strs == cell1clone.strs );
  19. System.out.println( cell1.leg == cell1clone.leg );
  20. } catch (CloneNotSupportedException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. }
  24. }
  25. }

输出结果如下:


看到 输出的  克隆和 被克隆对象里面的引用 两个地址是不同的,至此完成 深度克隆。







声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/68491
推荐阅读
相关标签
  

闽ICP备14008679号