Java学习之路4--原型模式(浅拷贝、深拷贝)
什么是原型模式
原型模式就是:
1.用原型实例指定创建对象的种类,并且通过克隆这些原型,创建新的对象。克隆创建的新对象中的原始值并不由构造函数决定,而是由被克隆的对象决定。
2.原型模式是一种创建型设计模式,运行一个对象再创建另外一个可定制的对象,无需知道如何创建的细节。
工作原理:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实现创建,即 对象.clone()。
浅拷贝的原型模式
题目
有一只羊hugo,姓名为 : hugo,年龄为 :2,颜色为 :蓝色,请编写程序创建和tom羊属性完全相同的10只羊。
传统实现
利用for循环与构造函数,对10只羊进行相同的数据赋值:
public Sheep(String name,int age,String color){
this.name=name;
this.age=age;
this.color=color;
}
for(int i=0;i<=9;i++)
{
Sheep hugo[i]=new Sheep("hugo",2,"blue");
}
运用原型模式的浅克隆实现
通过实现Cloneable接口,将clone的protected改成public,再调用super.clone()。
//实现Cloneable接口,完成clone
public Sheep clone() throws CloneNotSupportedException
{
//返回的是Object类型,要强制类型转换
return (Sheep)super.clone();
}
for(int i=0;i<=9;i++)
{
Sheep a[i];
try {
a[i] = hugo.clone();
System.out.println(a[i].toString());
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
深拷贝的原型模式
1.什么是深拷贝
理解深拷贝之前,我们要先分清楚什么是引用数据类型,什么是值数据类型。
值数据类型:就是像int,string等的8大基本数据类型。
引用数据类型:就是像对象、数组、可变变量这些数据类型。在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。
在浅拷贝中,我们的clone函数只能进行值数据类型的克隆,让值数据类型新建了属于自己的内存地址去保存。但是对于引用数据类型还是共用内存地址的。所以要进行深拷贝,必须要让引用数据类型新建一个内存地址去存储。
例子证明(运用浅拷贝进行引用数据的拷贝)
当数据类型为引用数据类型(以数组为例)时:
private String[] family=new String[3];
//在构造函数中初始化为father
family[0]="father";
进行浅拷贝:
public Deepsheep clone() throws CloneNotSupportedException
{
//进行浅拷贝
return (Deepsheep)super.clone();
}
System.out.println("hugo's father "+hugo.getfather());
System.out.println("a's father "+a.getfather());
a.tofamily("son");
System.out.println("hugo's father "+hugo.getfather());
System.out.println("a's father "+a.getfather());
输出:
hugo’s father father
a’s father father
hugo’s father son
a’s father son
从输出可以知道,当我们改变其中一个克隆对象的family[]数据时,其他的克隆对象包括本体一并改变了。说明他们都是共用一个存储内存,所以浅拷贝拷贝不了引用数据类型。当我们想对引用数据类型进行拷贝时,就要使用到深拷贝了。
2.怎么实现深拷贝
深拷贝实现方式1 :重写clone方法来实现深拷贝
//实现Cloneable接口,完成clone
public Deepsheep clone() throws CloneNotSupportedException
{
//先进行浅拷贝
Deepsheep sheep=null;
sheep=(Deepsheep)super.clone();
//再对引用数据类型进行单独实现拷贝方法
sheep.family=(String[])family.clone();
return sheep;
}
输出:
hugo’s father father
a’s father father
hugo’s father father
a’s father son
可以看到对其中一个对象进行更改不会影响到其他克隆对象,说明内存也重新分配了,达到了深拷贝的效果。
在对对象数据类型进行深拷贝时,要先在前一对象中实现浅/深拷贝,再在本层对象中进行调用来实现深拷贝。
深拷贝实现方式2 :通过对象序列化实现深拷贝
(后续再补)