Spring中常见的设计模式——原型模式
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);
}
}
Spring中常见的设计模式——原型模式的更多相关文章
- Spring中常见的设计模式——代理模式
一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...
- Spring中常见的设计模式——策略模式
策略模式(Strategy Pattern) 一.策略模式的应用场景 策略模式的应用场景如下: 系统中有很多类,而他们的区别仅仅在于行为不同. 一个系统需要动态的在集中算法中选择一种 二.用策略模式实 ...
- Spring中常见的设计模式——委派模式
一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...
- Spring中常见的设计模式——工厂模式
一.简单工厂模式 简单工厂模式(Simple Factory Pattern)由一个工厂对象决定创建哪一种产品类的实例,简单工厂模式适用于工厂类负责创建对象较少的情况,且客户端只需要传入工厂类的参数, ...
- Spring中常见的设计模式——模板模式
一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...
- Spring中常见的设计模式——适配器模式
一.适配器模式的应用场景 适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期待的另一个接口,使原本接口不兼容的类可以一起工作,属于构造设计模式. 适配器适用于以下几种业务场景: ...
- 设计模式:JDK和Spring中常见的设计模式
设计模式 总结 类 工厂模式 封装创建过程,只对结果负责 BeanFactory.Calender 单例模式 全局唯一 ApplicationContext.Calender 原型模式 多重影分身之术 ...
- Spring中常见的设计模式——单例模式
一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletCon ...
- spring 中常用的设计模式
一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...
随机推荐
- Android_Bundle
1 Bundle介绍 Bundle主要用于传递数据:它保存的数据,是以key-value(键值对)的形式存在的. 我们经常使用Bundle在Activity之间传递数据,传递的数据可以是boolean ...
- java常用类Time
LocalDate:IOS格式(yyyy-MM-dd)日期 LocalTime:表示一个时间 LocalDateTime:表示时间日期 Instant 时间线上的瞬时点,可以用来记录应用程序中的时间时 ...
- 作为一名程序员,你真正了解CDN技术吗?
本文导读: 物流仓库配送如何加速 静态资源文件部署方式 静态资源加速之CDN技术 解析过程中的名词解释 最后的总结 1.物流仓库配送如何加速 我们还是从生活中购物的例子来展开. 将时光倒回到几年前,在 ...
- ABAP中将Unicode字符串转换成中文的方法
以下为示例代码: DATA: LV_UNICODE TYPE STRING, "Unicode字符串 LV_CHINESE TYPE STRING. ...
- mock和axios常见的传参方式
第一次接手项目,传参方式还有些吃力,因此做一下总结. 首先我们需要会看swagger中的接口.里面写了某个接口需要接收什么样的值,前端怎么传递这个值 在mock中的传参方式: mock中传参的方式有两 ...
- OPTIONS 请求引发的分析
阅读提纲: 为什么会出现 OPTIONS 请求? 什么情况下会出现 OPTIONS 请求? OPTIONS 请求会发送什么内容? 跨域前端访问后端时,所有的 Ajax HTTP 请求都会先发送一个 O ...
- CSPS模拟 98
T1 待改 T2 这道题的爆炸充分说明我最近已经颓到一定境界了 考虑到总步数不可能超过n 直接枚举总步数,那么任意时刻对末态的影响就是确定的 T3 两遍最短路,一遍从-1的限制考虑求出允许的最早时间, ...
- SpringBoot Web篇笔记(一)
摘要 文章是根据江南一点雨(松哥)的视频进行总结 江南一点雨博客 全局异常处理 通常情况下,我们都需要对自己定义的异常进行相应的处理.捕获指定的异常方式如下: @ControllerAdvice pu ...
- 最新开源JavaScript 图表库 ECharts推荐
ECharts是一款由百度前端技术部开发的,基于Javascript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表. ECharts 提供大量常用的数据可视化图表,底层基于Z ...
- Elastic Stack 开源的大数据解决方案
目的 本文主要介绍的内容有以下三点: 一. Elastic Stack是什么以及组成部分 二. Elastic Stack前景以及业务应用 三. Elasticsearch原理(索引方向) 四. El ...