1、原型模式应用场景

  当遇到大量耗费劳动力的 get,set赋值场景时,如下:

public class SetGetParam {
public void setParam(UserDto userDto) {
User user = new User();
user.setAge(userDto.getAge());
//...
     userDao.addUser(user);
}
}

  原型模式(Prototype pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式主要适用于以下:

  (1)类初始化消耗资源较多;

  (2)使用new 生成一个对象需要非常繁琐的过程(数据准备访问权限等);

  (3)构造函数比较复杂;

  (4)在循环体中产生大量对象;

  在spring中用到的原型模式有:scope="prototype" ,还有常用的JSON.parseObject()也是一种原型模式

2、浅克隆

  创建具体需要克隆的类:

@Data
public class User {
private String name; private Integer age; private List<String> hobbies; public UserDto clone() {
UserDto dto = new UserDto();
dto.setAge(this.age);
dto.setName(this.name);
dto.setHobbies(this.hobbies);
return dto;
}
}

  创建Client:

public class Client {
private User user; public Client(User user) {
this.user = user;
} public UserDto startClone(User user) {
return user.clone();
}
}

  测试克隆,对比复制过来的值是否有自己的地址,还是用的原来的地址

public class PrototypeTest {
public static void main(String[] args) {
//创建具体需要克隆的对象
User user = new User();
user.setName("皮肤黝黑的小白");
user.setHobbies(new ArrayList<>());
System.out.println(user);
//创建Client对象,准备开始克隆
Client client = new Client(user);
UserDto dto = client.startClone(user);
System.out.println(dto);
System.out.println(user.getHobbies() == dto.getHobbies());
System.out.println(user.getName() == dto.getName());
}
}

  结果:

User(name=皮肤黝黑的小白, age=null, hobbies=[])
UserDto(name=皮肤黝黑的小白, age=null, hobbies=[])
true
true

  从测试结果可以看出:hobbies和name的内存地址是相同的,这说明我们并没有重新创建对象,这就是浅克隆。

3、深克隆

  采用序列化反序列化克隆,实现深克隆,

@Data
public class UserDeepClone implements Cloneable {
private String name; private Integer age; private List<String> hobbies; @Override
protected Object clone() throws CloneNotSupportedException {
return this.deepClone();
} public UserDto deepClone() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
UserDto dto = (UserDto) ois.readObject();
return dto;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
public class DeepCloneTest {
public static void main(String[] args) {
DeepCloneTest deepCloneTest = new DeepCloneTest();
UserDeepClone user = new UserDeepClone();
user.setName("皮肤黝黑的小白");
user.setHobbies(new ArrayList<>());
System.out.println(user);
UserDto dto = null;
try {
dto = (UserDto) deepCloneTest.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(dto);
System.out.println(user.getName() == dto.getName());
System.out.println(user.getHobbies() == dto.getHobbies());
}
}

4、克隆破坏单例

  深克隆会破坏单例,其实防御方式很简单,单例类不要实现Cloneable接口即可。

5、ArrayList中clone()方法的源码

    public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}

  

  

最新文章

  1. MongoDB学习笔记三—增删改文档上
  2. RabbitMQ总结概念
  3. 微信调试、API、AJAX的调试 SocketLog
  4. 批处理命令——goto 和 :
  5. VMwareTools安装笔记
  6. Spring整合Hibernate详细步骤
  7. javax.inject中@Inject、@Named、@Qualifier和@Provider用法
  8. Lowest Common Ancestor
  9. [翻译]了解ASP.NET底层架构(八)
  10. iis7设置404页面不生效的原因
  11. jquery 根据数据库值设置radio的选中
  12. SpringBoot简单打包部署(附工程)
  13. 更改系统盘符后DFS无法复制故障处理
  14. google的python语言规范
  15. 分布式文档系统_document查询内部原理
  16. Nginx负载均衡初识
  17. BZOJ1001: [BeiJing2006]狼抓兔子【最短路+对偶图】
  18. 三维凸包求内部一点到表面的最近距离(HDU4266)
  19. uva10655矩阵快速幂
  20. OpenCV中Mat的属性

热门文章

  1. java中的Static、final、Static final各种用法详解
  2. json基本内容
  3. SpringBoot整合MybatisPlus3.X之自定义Mapper(十)
  4. docker安装sshd
  5. shell 脚本中的注释详解
  6. SQL 中更新一个表的数据是从另外的表(或者自己本身的表)查询出来的
  7. 学习笔记28_MVC异步请求
  8. python--&gt;二进制的用法
  9. python学习之【第十四篇】:Python中的装饰器
  10. 最新JetBrainsPyCharm自动部署Python(Django,tornado等)项目至远程服务器