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中常见的设计模式——原型模式的更多相关文章

  1. Spring中常见的设计模式——代理模式

    一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...

  2. Spring中常见的设计模式——策略模式

    策略模式(Strategy Pattern) 一.策略模式的应用场景 策略模式的应用场景如下: 系统中有很多类,而他们的区别仅仅在于行为不同. 一个系统需要动态的在集中算法中选择一种 二.用策略模式实 ...

  3. Spring中常见的设计模式——委派模式

    一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...

  4. Spring中常见的设计模式——工厂模式

    一.简单工厂模式 简单工厂模式(Simple Factory Pattern)由一个工厂对象决定创建哪一种产品类的实例,简单工厂模式适用于工厂类负责创建对象较少的情况,且客户端只需要传入工厂类的参数, ...

  5. Spring中常见的设计模式——模板模式

    一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...

  6. Spring中常见的设计模式——适配器模式

    一.适配器模式的应用场景 适配器模式(Adapter Pattern)是指将一个类的接口转换成用户期待的另一个接口,使原本接口不兼容的类可以一起工作,属于构造设计模式. 适配器适用于以下几种业务场景: ...

  7. 设计模式:JDK和Spring中常见的设计模式

    设计模式 总结 类 工厂模式 封装创建过程,只对结果负责 BeanFactory.Calender 单例模式 全局唯一 ApplicationContext.Calender 原型模式 多重影分身之术 ...

  8. Spring中常见的设计模式——单例模式

    一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletCon ...

  9. spring 中常用的设计模式

    一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...

随机推荐

  1. 不同的phper该如何区别使用swoole和workerman?

       那么我们该怎样去区别应用swoole和workerman?                workerman workerman纯php写的,swoole是php的c扩展,性能肯定更高,百度.腾 ...

  2. 面对对象高阶+反射+魔法方法+单例(day22)

    目录 昨日内容 组合 封装 property装饰器 多态 鸭子类型 今日内容 classmethod staticmethod 面对对象高级 isinstance issubclass 反射(重要) ...

  3. Spring Boot项目在多环境下(开发、生产或测试环境)调用不同配置文件方式

    写在前面 最近由于项目要求,原先的项目只有开发环境的项目配置,后来不利于线上测试,于是,最近对于SpringBoot这部分多环境配置在网上查找了相关资料,并实现了配置,于是为了防止遗忘,特在此进行总结 ...

  4. Flask+WebSocket实现群聊与单聊功能

    在开始我们的程序代码之前,先来了解一下相关的基础知识: 1.什么是websocket? (1)WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议.WebSocket ...

  5. Android自定义控件:自适应大小的文本控件

    需求 自适应大小的文本: 效果图: 项目开发中,开发人员根据UI人员提供的一套尺寸,布局了一些带文本的页面, 往往会少考虑一些数据极限的问题,造成机型屏幕适配问题. 例如: 文本(或数值)长度可变,如 ...

  6. 【Java必修课】String.intern()原来还能这么用(原理与应用)

    1 简介 String.intern()是JDK一早就提供的native方法,不由Java实现,而是底层JVM实现,这让我们对它的窥探提高了难度.特别是在Oracle收购了Sun公司后,源代码不开源了 ...

  7. [考试反思]1008csp-s模拟测试64:契机

    暴力没打满...有点垃圾... 考得稍绝望,啥也不会啊??? T3的测试点分治还写挂了... 其实就是没有沉下心好好的思考,在三道题上来回切换结果一个成型思路都没有 T2既然已经想到那一步了居然没有继 ...

  8. UWP 带左右滚动按钮的横向ListView———仿NetFlix首页河的设计

    也是之前写的控件了,模仿NetFlix的河的设计. 大体要求如下: 1. 横向的ListView 2. 左右按钮,可以左右移动河卡片,左右的滚动条不可见 3. 左右按钮仅在鼠标Hover事件中可见 大 ...

  9. netty源码解析(4.0)-28 ByteBuf内存池:PooledByteBufAllocator-把一切组装起来

    PooledByteBufAllocator负责初始化PoolArena(PA)和PoolThreadCache(PTC).它提供了一系列的接口,用来创建使用堆内存或直接内存的PooledByteBu ...

  10. Wycieczki 线性代数

    B. Wycieczki 题目描述 给定一张n个点m条边的带权有向图,每条边的边权只可能是1,2,3中的一种.将所有可能的路径按路径长度排序,请输出第k小的路径的长度,注意路径不一定是简单路径,即可以 ...