设计模式-总览https://mp.csdn.net/mp_blog/creation/editor/122202507 设计模式并不是Java独有的,但是Java提供了一个接口Cloneable,只要有一个类实现了该接口则可以在内存中直接拷贝对象,让原型模式的实现变的非常的简单。但是Cloneable接口是浅拷贝(这个就要去理解一下深拷贝和浅拷贝的区别了)。所以当一个对象进行clone时,如果对象中存在对象,如User对象有个属性Department dept是对象,则克隆出来的对象和源对象的dept属性指向同一内存地址,如某一对象对其进行了更改,则都进行了更改,再拷贝给其他人的也都是改变后的。由于线上环境比较复杂,所以这种一般还是建议使用深拷贝。
使用深深拷贝有两种方式:第一就是在上面的情况,对象内部的所有对象都实现Cloneable接口,即Department类也实现Cloneable接口。第二就是可以使用序列化方式(当然这不是很建议,可以查看之前写的序列化相关的博客Java序列化)。
应用场景:
1、因为Cloneable的clone()方法在内存中进行实现的,所以效率非常高。如果有大量差不多的对象需要创建并且大多数字段都差不多,每次去进行new则会比较影响性能。
2、被拷贝之后不能判断数据会怎么进行修改,则需要对源模板对象进行保护。比如Spring 中或者原型对象时。但是个人觉得这种场景不会很多,微服务之后的每个jvm内部,对象做了什么还是比较清楚的。跨进程的调用进行了序列化和反序列化也不用考虑太多。
一、原型模式实现
自己模拟一个场景,需要初始化很多的对象,该对象内部有很多字段是值相同的。
@Data
public class User implements Cloneable {
private Long id;
private String name;
private Department department;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", department=" + "{deptId='" + department.getId()
+ "',deptName='" + department.getName() + "'}" +
'}';
}
}
@Data
public class Department implements Cloneable {
private Long id;
private String name;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
个人觉得原型模式可能经常和简单工厂模式一起进行使用。
public class UserInitFactory {
/**
* 为了最后方便大于原型的对象数据,修改为public方法
*/
public static final User user = new User();
static {
Department department = new Department();
department.setId(123L);
department.setName("研发部");
user.setId(1L);
user.setName("kevin");
user.setDepartment(department);
}
/**
* 个人觉得原型模式可能经常牵扯 简单工厂模式
* @return 用户
*/
public static User getUser() {
try {
return (User)user.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
测试类:
public class PrototypeTest {
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
User user = UserInitFactory.getUser();
user.setId(i + 1L);
user.setName("名称" + i);
System.out.println("生产出来第" + i + "个模板的用户:" + user);
}
System.out.println("原模板数据为:" + UserInitFactory.user.toString());
}
}
输出:
。。。。。。
生产出来第998个模板的用户:User{id=999, name='名称998', department={deptId='123',deptName='研发部'}}
生产出来第999个模板的用户:User{id=1000, name='名称999', department={deptId='123',deptName='研发部'}}
原模板数据为:User{id=1, name='kevin', department={deptId='123',deptName='研发部'}}
二、Spring中的原型模式分析
。。。