原型模式(Prototype Pattern
)是归属于创建型模式的一个分支,是通过使用给一个已经创建的实例作为原型,通过复制当前的原型对象来实现创建一个和原型对象相同的新的对象的方式。Java
中的原型模式主要可以通过Java
提供的clone
方法来实现对象的克隆。通过拷贝方式的不同又可分为浅拷贝和深拷贝,如下介绍两种方式的创建和使用的不同。
浅拷贝
浅拷贝是将一个对象复制后,基本数据类型的变量都会重新创建,而数组、容器对象、引用对象等都不会拷贝,指向的还是原对象所指向的地址。浅拷贝实现 Cloneable
,重写clone
方法。
常用API功能如下:
- 使用Spring中
BeanUtils
和PropertyUtils
直接进行对象复制(对于Android
端的java
代码并不适用) - 实现
Cloneable
接口(推荐使用) - Arrays.copyOf(),但在ArrayList中实现了深拷贝的效果
1、创建地址类
/**
* 地址类
*/
@Data
@Accessors(chain = true)
public class Address {
private String province;
private String municipality;
private String region;
}
2、创建用户类
/**
* 用户类
*/
@Data
public class User implements Cloneable {
private String userName;
private Address address;
@Override
protected User clone() {
try {
return (User) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
3、使用
public static void main(String[] args) {
User user1 = new User();
user1.setUserName("张三");
user1.setAddress(new Address().setProvince("甘肃省").setMunicipality("兰州市").setRegion("七里河区"));
User clone = user1.clone();
System.out.println(user1);
System.out.println(clone);
System.out.println(user1 == clone); // false
System.out.println(user1.getAddress() == clone.getAddress()); // true 引用的同一个对象,修改其中一个用户的地址会影响到另一个用户的地址
}
深拷贝
深拷贝是将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。深拷贝是通过实现 Serializable
读取二进制流。
API使用:
- 每个对象都需实现
Cloneable
接口并重写Object
中的clone()
方法 - 需要通过实现
Serializable
接口实现序列化,这也是串口、蓝牙通信常用的方式 Apache Commons
工具SerializationUtils.clone(T object)
功能- 通过
JSON
工具实现数据深拷贝,其原理和Serializable
大同小异 - 通过构造方法实现深拷贝(
new
对象会给对象创建一个新的地址空间)
1、创建地址类
/**
* 地址类
*/
@Data
@Accessors(chain = true)
public class Address implements Serializable {
private String province;
private String municipality;
private String region;
}
2、创建用户类
/**
* 用户类
*/
@Data
public class User implements Cloneable, Serializable {
private String userName;
private Address address;
@Override
protected User clone() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (User) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
3、使用
public static void main(String[] args) {
User user1 = new User();
user1.setUserName("张三");
user1.setAddress(new Address().setProvince("甘肃省").setMunicipality("兰州市").setRegion("七里河区"));
User clone = user1.clone();
System.out.println(user1);
System.out.println(clone);
System.out.println(user1 == clone);
System.out.println(user1.getAddress() == clone.getAddress());
}