简介
原型模式是创建型模式的一种,其主要是用于创建重复的对象,即将一个对象克隆成另一个一样的对象。对于一些复杂的对象,其创建效率十分高效。但该方式也有一个问题,该克隆是一个浅拷贝,新克隆出来的对象中引用的对象的地址与原对象是同一个。关于深拷贝和浅拷贝,文末会做进一步探讨。
demo示例
代码
该模式的代码较为简单,首先克隆的类需要实现cloneable接口,并重写clone方法。
import java.util.Arrays;
public class City implements Cloneable{
private String name;
private String location;
private String[] districts = {"d1", "d2", "d3", "d4"};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String[] getDistricts() {
return districts;
}
public void setDistricts(String[] districts) {
this.districts = districts;
}
@Override
public String toString() {
return "City{" +
"name='" + name + '\'' +
", location='" + location + '\'' +
", districts=" + Arrays.toString(districts) +
'}';
}
@Override
public Object clone() {
try {
return super.clone();//调用父clone方法
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
客户端调用
public class Test {
public static void main(String[] args) {
City city1 = new City();
city1.setLocation("west");
city1.setName("chongqing");
System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
}
}
深拷贝与浅拷贝
什么是深拷贝和浅拷贝
深拷贝和浅拷贝是针对object类型的数据,对于浅拷贝,拷贝的是某个对象的指针而没有拷贝指针对应的数据,即对于object类型的数据,新对象和老对象只向的是同一块内存区域。对于深拷贝,其会将所有的object数据全部拷贝一份,此时新对象和老对象只向的是不同的内存区域。
cloneable是深拷贝还是浅拷贝
我们通过一个测试实验看一下cloneable是深拷贝还是浅拷贝,还是基于上面的City类:
public class Test {
public static void main(String[] args) {
City city1 = new City();
city1.setLocation("west");
city1.setName("chongqing");
System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
System.out.println("---------------");
City city2 = (City) city1.clone();
String[] cloneArr = city2.getDistricts();
cloneArr[0] = "d1_new";
city2.setName("chengdu");
System.out.println(city2);//City{name='chengdu', location='west', districts=[d1_new, d2, d3, d4]}
System.out.println(city1);//City{name='chongqing', location='west', districts=[d1_new, d2, d3, d4]}
}
}
从上面的测试可以看出,对于clone出来的对象,我们将其districts数组中的第一个元素进行修改,最后原对象中对应的值也被修改了,因此我们可以得出结论,cloneable是浅拷贝。
如何实现深拷贝
要实现深拷贝,最常用的方法是对原对象进行序列化,然后再恢复。还是以City对象为例,我们先将其序列化成json,然后再恢复,我们使用google的gson进行演示。 gson的坐标为:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
测试代码如下
public class Test2 {
public static void main(String[] args) {
City city1 = new City();
city1.setLocation("west");
city1.setName("chongqing");
System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
System.out.println("---------------");
Gson gson = new Gson();
String json = gson.toJson(city1);
City city2 = gson.fromJson(json, City.class);
String[] cloneArr = city2.getDistricts();
cloneArr[0] = "d1_new";
city2.setName("chengdu");
System.out.println(city2);//City{name='chengdu', location='west', districts=[d1_new, d2, d3, d4]}
System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
}
}
对于通过json新建出来的对象ctity2,我们修改其districts中的第一个对象为d1_new,其修改值并没有影响到city1。