Spring中常见的设计模式——原型模式
2024-09-01 15:42:56
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);
}
}
最新文章
- MongoDB学习笔记三—增删改文档上
- RabbitMQ总结概念
- 微信调试、API、AJAX的调试 SocketLog
- 批处理命令——goto 和 :
- VMwareTools安装笔记
- Spring整合Hibernate详细步骤
- javax.inject中@Inject、@Named、@Qualifier和@Provider用法
- Lowest Common Ancestor
- [翻译]了解ASP.NET底层架构(八)
- iis7设置404页面不生效的原因
- jquery 根据数据库值设置radio的选中
- SpringBoot简单打包部署(附工程)
- 更改系统盘符后DFS无法复制故障处理
- google的python语言规范
- 分布式文档系统_document查询内部原理
- Nginx负载均衡初识
- BZOJ1001: [BeiJing2006]狼抓兔子【最短路+对偶图】
- 三维凸包求内部一点到表面的最近距离(HDU4266)
- uva10655矩阵快速幂
- OpenCV中Mat的属性
热门文章
- java中的Static、final、Static final各种用法详解
- json基本内容
- SpringBoot整合MybatisPlus3.X之自定义Mapper(十)
- docker安装sshd
- shell 脚本中的注释详解
- SQL 中更新一个表的数据是从另外的表(或者自己本身的表)查询出来的
- 学习笔记28_MVC异步请求
- python-->;二进制的用法
- python学习之【第十四篇】:Python中的装饰器
- 最新JetBrainsPyCharm自动部署Python(Django,tornado等)项目至远程服务器