设计模式(浅拷贝与深拷贝详解,以及通过对象序列化实现深拷贝)

2023-02-05 0 1,077

概要

蓝本商业模式是两个建立型设计商业模式,蓝本说明那个商业模式有两个样板工程示例,使用者从那个示例第一类中拷贝两个外部特性完全一致的第一类,也是他们一般来说说的布季夫,被拷贝的第一类是蓝本。蓝本商业模式常见于建立繁杂的或是外部结构费时的实例,拷贝两个早已存有的示例能使程序代码更为高效率。

类亲密关系

设计模式(浅拷贝与深拷贝详解,以及通过对象序列化实现深拷贝)
Client:应用程序使用者Prototype:tcsh或是USB,新闻稿具有clone潜能ConcretePrototype:具体内容的蓝本类

蓝本商业模式是一个很单纯的商业模式,同时实现两个USB,改写两个方式即顺利完成了蓝本商业模式。当两个第一类建立操作过程很繁杂,比如说建立第一类须要伍润泉表头,这时,他们能依照已近的第一类展开复本,而无须重视建立的技术细节。

单纯同时实现

CloneableUSB或其同时实现类

具体来说蓝本类须要同时实现java.lang.CloneableUSB,后改写Object中的clone()方式。Cloneable是两个记号USB,多于同时实现了那个USB的类才能透过clone展开第一类的复本。假如不同时实现那个USB,则会放出极度

设计模式(浅拷贝与深拷贝详解,以及通过对象序列化实现深拷贝)

那时他们撰写两个蓝本类并同时实现CloneableUSB

//同时实现CloneableUSB public class Document implementsCloneable{private String mText; private String mText2; private String mText3; private String mText4; //两个引用类型的变量 privateUserInfo userInfo;//外部结构函数须要的表头有很多 public Document(String mText, String mText2, String mText3, StringmText4, UserInfo userInfo) {super(); this.mText = mText; this.mText2 = mText2; this.mText3 = mText3; this.mText4 = mText4;this.userInfo = userInfo; } //clone方式 返回super.clone()返回的第一类 @Override protected Objectclone() throws CloneNotSupportedException { Documentdocument = (Document)super.clone(); return document; }@Override public String toString() { return “Document [hashCode=”+this.hashCode()+“, “+“mText=”+ mText +“, mText2=” + mText2 + “, mText3=” + mText3 + “, mText4=” + mText4 + “, userInfo=” + userInfo +“]”; } … 拷贝代码

引用类UserInfo(用于演示引用类型变量)

public class UserInfo implements Cloneable{ publicString name;public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return “UserInfo [name=” + name + “]”; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } 拷贝代码

透过Document那个类能看到,由于其外部结构函数所需要的参数很多,要外部结构两个第一类的成本是很大的,所以对于这种情况,能考虑使用clone来建立第一类,能节省很多成本。

Client同时实现

public class Client { public static void main(String[] args) throws CloneNotSupportedException { UserInfo userInfo = newUserInfo(); userInfo.setName(“xxx”); //建立Document示例第一类 Document document = new Document(“1”,“2”,“3”,“4”,userInfo); //得到document的布季夫第一类 Document clone = (Document)document.clone(); System.out.println(“document=”+document); System.out.println(“clone=”+clone); } } 拷贝代码

透过document.clone()方式很单纯的就能得到两个布季夫好的第一类,查看一下打印的结果

document=Document [hashCode=2018699554, mText=1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=xxx]] clone=Document [hashCode=1311053135, mText=1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=xxx]] 拷贝代码

能看到clone第一类和原第一类的hashCode值是不同的,也是说这是两个不同的第一类。透过这种方式能很方便地去建立第一类。

深拷贝和浅复本

浅复本

假如第一类中有引用类型,比如说UserInfo,当他们试图去修改那个引用时,可能会引发一些问题,具体内容来看一下。那时修改一下布季夫第一类的值,然后输出一下

public static voidmain(String[] args) throws CloneNotSupportedException { UserInfo userInfo = newUserInfo(); userInfo.setName(“xxx”); Document document = new Document(“1”,“2”,“3”,“4”,userInfo); //对原始第一类的String类型展开修改 document.setmText(“text1”); //得到布季夫第一类 Document clone = (Document)document.clone(); //修改布季夫第一类的引用数据类型userInfo clone.getUserInfo().setName(“yyy”); //修改布季夫第一类的String类型变量 clone.setmText(“text2”); System.out.println(“document=”+document); System.out.println(“clone=”+clone); } 拷贝代码

以上代码我透过clone方式得到了布季夫第一类,同时修改了布季夫第一类的userinfo的内容,并同时修改了原始第一类和布季夫第一类的String类型做了修改。产看一下结果

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=yyy]] clone=Document [hashCode=1311053135, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [name=yyy]] 拷贝代码

看到问题了吗,我只是修改了布季夫第一类的userinfo,但是原始第一类的userinfo也被修改了,从这里他们能发现,对于引用类型的变量,布季夫第一类和原始第一类指向的是同一块内存空间,当第一类发生改变,原始第一类和布季夫对象都会发生相应的改变,他们修改一下UserInfo的打印,将其内存地址一并输出

UserInfo.java @Override public String toString() { return “UserInfo [hashcode=”+this.hashCode()+“, “+“name=” + name + “]”; } 拷贝代码

再次执行Client的打印

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=yyy]] clone=Document [hashCode=118352462, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=yyy]] 拷贝代码

能看到,document的userinfo和clone第一类的userinfo指向的是同样的地址。

深复本

对于这样的问题应该如何解决呢?他们修改一下Document的clone方式

Document.java @Override protected Objectclone() throws CloneNotSupportedException { Documentdocument = (Document)super.clone(); //对于document的引用类型展开clone的操作 document.setUserInfo((UserInfo)userInfo.clone()); return document; } 拷贝代码

透过以上的修改,他们再来执行一下打印的操作

document=Document [hashCode=2018699554, mText=text1, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1311053135, name=xxx]] clone=Document [hashCode=118352462, mText=text2, mText2=2, mText3=3, mText4=4, userInfo=UserInfo [hashcode=1550089733, name=yyy]] 拷贝代码

看到了吧,这次的打印不同了,多于布季夫第一类的值修改了,而原始第一类的值并没有被修改,同时,他们所指向的userinfo的地址也不同了,这是深复本。

小结

他们透过两个示例来认识了蓝本商业模式,同时又透过对两个引用类型变量的修改,来理解深复本和浅复本的含义,这里再来总结一下两者的概念。

浅复本:是把蓝本第一类中成员变量为值类型的特性都赋值给布季夫第一类,把蓝本第一类中的成员变量为引用类型的引用地址也拷贝给布季夫第一类,也是蓝本第一类中假如有成员变量为引用第一类,则此引用第一类的地址是共享给蓝本第一类和布季夫第一类的。浅复本只会拷贝蓝本第一类,但不会拷贝其所引用的第一类

深复本:将蓝本第一类中的所有类型,无论是值类型还是引用类型,都拷贝一份给布季夫第一类,深复本会把蓝本第一类和蓝本第一类所引用的第一类,都拷贝一份给布季夫第一类。

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务