| 1) 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。 |
| 2) 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。 |
| 因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值 |
| 3) 前面我们克隆羊就是浅拷贝 |
| 4) 浅拷贝是使用默认的 clone()方法来实现 |
| sheep = (Sheep) super.clone(); |
| package com.atguigu.prototype.improve; |
| |
| public class Sheep implements Cloneable { |
| |
| private String name; |
| |
| private int age; |
| |
| private String color; |
| |
| private String address = "蒙古羊"; |
| |
| public Sheep friend; |
| |
| public Sheep(String name, int age, String color) { |
| super(); |
| this.name = name; |
| this.age = age; |
| this.color = color; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public int getAge() { |
| return age; |
| } |
| |
| public void setAge(int age) { |
| this.age = age; |
| } |
| |
| public String getColor() { |
| return color; |
| } |
| |
| public void setColor(String color) { |
| this.color = color; |
| } |
| |
| @Override |
| public String toString() { |
| return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]"; |
| } |
| |
| @Override |
| protected Object clone() { |
| Sheep sheep = null; |
| try { |
| sheep = (Sheep)super.clone(); |
| } catch (Exception e) { |
| |
| System.out.println(e.getMessage()); |
| } |
| |
| return sheep; |
| } |
| |
| } |
| |
| package com.atguigu.prototype.improve; |
| |
| public class Client { |
| |
| public static void main(String[] args) { |
| System.out.println("原型模式完成对象的创建"); |
| Sheep sheep = new Sheep("tom", 1, "白色"); |
| |
| sheep.friend = new Sheep("jack", 2, "黑色"); |
| Sheep sheep2 = (Sheep)sheep.clone(); |
| Sheep sheep3 = (Sheep)sheep.clone(); |
| Sheep sheep4 = (Sheep)sheep.clone(); |
| Sheep sheep5 = (Sheep)sheep.clone(); |
| |
| System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode()); |
| System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode()); |
| System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode()); |
| System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode()); |
| } |
| |
| } |
| |
| # 该案例中打印出来的sheep2.friend都指向了1个对象 |
| 1) 复制对象的所有基本数据类型的成员变量值 |
| 2) 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝 |
| 3) 深拷贝实现方式1:重写clone方法来实现深拷贝 |
| 4) 深拷贝实现方式2:通过对象序列化实现深拷贝(推荐) |
| package com.atguigu.prototype.deepclone; |
| import java.io.Serializable; |
| public class DeepCloneableTarget implements Serializable, Cloneable { |
| |
| private static final long serialVersionUID = 1L; |
| |
| private String cloneName; |
| |
| private String cloneClass; |
| |
| |
| public DeepCloneableTarget(String cloneName, String cloneClass) { |
| this.cloneName = cloneName; |
| this.cloneClass = cloneClass; |
| } |
| |
| |
| @Override |
| protected Object clone() throws CloneNotSupportedException { |
| return super.clone(); |
| } |
| } |
| |
| package com.atguigu.prototype.deepclone; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| |
| public class DeepProtoType implements Serializable, Cloneable{ |
| |
| public String name; |
| |
| public DeepCloneableTarget deepCloneableTarget; |
| |
| public DeepProtoType() { |
| super(); |
| } |
| |
| |
| @Override |
| protected Object clone() throws CloneNotSupportedException { |
| Object deep = null; |
| |
| deep = super.clone(); |
| |
| DeepProtoType deepProtoType = (DeepProtoType)deep; |
| deepProtoType.deepCloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone(); |
| return deepProtoType; |
| } |
| |
| |
| public Object deepClone() { |
| |
| ByteArrayOutputStream bos = null; |
| ObjectOutputStream oos = null; |
| ByteArrayInputStream bis = null; |
| ObjectInputStream ois = null; |
| try { |
| |
| bos = new ByteArrayOutputStream(); |
| oos = new ObjectOutputStream(bos); |
| oos.writeObject(this); |
| |
| bis = new ByteArrayInputStream(bos.toByteArray()); |
| ois = new ObjectInputStream(bis); |
| DeepProtoType copyObj = (DeepProtoType)ois.readObject(); |
| return copyObj; |
| } catch (Exception e) { |
| |
| e.printStackTrace(); |
| return null; |
| } finally { |
| |
| try { |
| bos.close(); |
| oos.close(); |
| bis.close(); |
| ois.close(); |
| } catch (Exception e2) { |
| |
| System.out.println(e2.getMessage()); |
| } |
| } |
| } |
| |
| } |
| |
| package com.atguigu.prototype.deepclone; |
| |
| public class Client { |
| |
| public static void main(String[] args) throws Exception { |
| DeepProtoType p = new DeepProtoType(); |
| p.name = "宋江"; |
| p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛"); |
| |
| |
| |
| |
| |
| |
| |
| DeepProtoType p2 = (DeepProtoType) p.deepClone(); |
| System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode()); |
| System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode()); |
| } |
| |
| } |
| 1) 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率 |
| 2) 不用重新初始化对象,而是动态地获得对象运行时的状态 |
| 3) 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码 |
| 4) 在实现深克隆的时候可能需要比较复杂的代码 |
| 5) 缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp原则 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术