原型模式 java_原型模式--java代码实现

本文详细介绍了Java中的原型模式,通过分析JVM内存中的栈和堆来理解对象创建、引用和克隆的过程。文章讨论了浅层克隆和深层克隆的区别,并提供了具体的代码示例来演示这两种克隆方式。最后,通过测试案例展示了浅层克隆和深层克隆在实际应用中的效果,强调了Java中默认的克隆为浅层克隆,而实现深层克隆需要额外的代码操作。
摘要由CSDN通过智能技术生成

原型模式

原型模式,属于对象创建型模式中的一种。通过复制原型对象的方法来创建一个对象实例,且该对象与原对象有相同的数据结构和值。类似我们在备份数据库信息的时候,将数据库中表的结构和数据的一同备份,生成一个数据库文件。

在Java环境中,要实现原型模式,要理解对象创建、引用和克隆的相关知识,在这里通过简单分析JVM的内存在对象创建、引用和克隆时栈和堆的内容变化,来深入理解原型模式是如何在Java环境中运作的。

1.简单理解JVM内存中栈和堆

栈:用来存放函数中定义的基本类型的变量和对象的引用变量。

堆:则是存放由new创建的对象和数组,对象内存储普通的变量和方法。对象创建后将其地址赋值给栈中的引用变量。

方法区:也是堆,这里面存放类代码、静态变量、静态方法和字符串常量等。

2.引用和克隆的区别

引用的示例图:

431659fcec1bd9a1d975d1eedaa5e772.png

克隆的示意图:

ac11aacdce12ed75516ef45ddce29b73.png

由示例图我们可以看出,引用,比如person2=person1,栈中两个不同的成员变量指向对中的同一个对象,他们两个的值是一样的,都是该对象在内存中的地址。而克隆是将对象复制一份包括数据结构和值,将复制出的对象的地址赋值给栈中的另外一个成员变量person2。

3.浅层克隆和深层克隆

有没有注意到一个问题,如果普通变量是一个引用变量,比如数组,列表或map,那么克隆是否把引用变量(person1中的friends)所引用的对象也给复制一份呢。其实并没有,只是将引用变量的变量名和值复制了一份,他们还是用的同一个引用对象,这就是浅层克隆。如浅层克隆示意图所示。那么如果想要把引用变量所指的对象也复制一份,则需要重新新建一个对应的对象,将值传入对象中,返回给复制后的引用变量person2中的friends中。如深层克隆示意图所示。

浅层克隆示意图:

e9c6ce4f57fe025d0c6942957bcbd6b4.png

深层克隆示意图:

103dbc3316137ed9d0ec33a9bac7689c.png

4.代码实现

Person类:

在Java中克隆该类需实现Cloneable接口,重写了Object的 clone() 方法,该方法会创建和返回一个Person类的一个复制,也就是上述所说的浅层复制。该类中添加了浅层克隆shallowClone()和深层克隆deepClone()。

packageprototype;importjava.util.ArrayList;importjava.util.List;public class Person implementsCloneable{//姓名

privateString name;//年龄

private intage;//朋友

private Listfriends;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}public ListgetFriends() {returnfriends;

}public void setFriends(Listfriends) {this.friends =friends;

}//重写toString方法

@OverridepublicString toString() {return "Person [name=" + name + ", age=" + age + ", friends=" + friends + "]";

}//浅层克隆

publicPerson shallowClone() {try{return (Person) super.clone();

}catch(CloneNotSupportedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}return null;

}//深层克隆

publicPerson deepClone() {try{

Person person= (Person) super.clone();

List newFriends = new ArrayList();for(String friend : this.getFriends()) {

newFriends.add(friend);

}

person.setFriends(newFriends);returnperson;

}catch(CloneNotSupportedException e) {//TODO Auto-generated catch block

e.printStackTrace();

}return null;

}

}

MainClass:

通过向列表中添加值来测试浅层克隆和深层克隆。具体代码中有注释,请看代码。

packageprototype;importjava.util.ArrayList;importjava.util.List;public classMainClass {public static voidmain(String[] args) {//创建对象person1

Person person1 = newPerson();//初始化对象

person1.setName("zhangsan");

person1.setAge(20);

List friends = new ArrayList();

friends.add("lisi");

friends.add("wangwu");

person1.setFriends(friends);//person2是浅层克隆

Person person2 =person1.shallowClone();//person3是深层克隆

Person person3 =person1.deepClone();//获取浅层克隆的friends的list对象

List person2_friends =person2.getFriends();//向引用对象中添加值

person2_friends.add("shallow");

person2.setFriends(person2_friends);//获取深层克隆的friends的list对象

List person3_friends =person3.getFriends();//向引用对象中添加值

person3_friends.add("deep");

person3.setFriends(person3_friends);

System.out.println("原型:"+person1);

System.out.println("浅层克隆:"+person2);

System.out.println("深层克隆:"+person3);

}

}

5.结果

64840caa359c28b353e7b513be73d54d.png

从结果中可以发现,浅层克隆的person2中向friends列表中添加的shallow朋友,而在原型person1中也添加了shallow,验证了前面的说法。深层克隆person3是在person2之前克隆的,所以没有添加shallow朋友,而之后添加的deep朋友也没有影响person1和person2中的friends列表。

6.总结

通过结合JVM内存中的栈和堆来解释原型模型,利用Java代码成功测试。可以发现Java中默认是的克隆模式是浅层克隆,不复制引用变量所对应的对象。那么对于深层次的克隆,需要编写对应代码来复制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值