1、原型模式应用场景

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

  1. public class SetGetParam {
  2. public void setParam(UserDto userDto) {
  3. User user = new User();
  4. user.setAge(userDto.getAge());
  5. //...
         userDao.addUser(user);
  6. }
  7. }

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

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

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

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

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

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

2、浅克隆

  创建具体需要克隆的类:

  1. @Data
  2. public class User {
  3. private String name;
  4.  
  5. private Integer age;
  6.  
  7. private List<String> hobbies;
  8.  
  9. public UserDto clone() {
  10. UserDto dto = new UserDto();
  11. dto.setAge(this.age);
  12. dto.setName(this.name);
  13. dto.setHobbies(this.hobbies);
  14. return dto;
  15. }
  16. }

  创建Client:

  1. public class Client {
  2. private User user;
  3.  
  4. public Client(User user) {
  5. this.user = user;
  6. }
  7.  
  8. public UserDto startClone(User user) {
  9. return user.clone();
  10. }
  11. }

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

  1. public class PrototypeTest {
  2. public static void main(String[] args) {
  3. //创建具体需要克隆的对象
  4. User user = new User();
  5. user.setName("皮肤黝黑的小白");
  6. user.setHobbies(new ArrayList<>());
  7. System.out.println(user);
  8. //创建Client对象,准备开始克隆
  9. Client client = new Client(user);
  10. UserDto dto = client.startClone(user);
  11. System.out.println(dto);
  12. System.out.println(user.getHobbies() == dto.getHobbies());
  13. System.out.println(user.getName() == dto.getName());
  14. }
  15. }

  结果:

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

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

3、深克隆

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

  1. @Data
  2. public class UserDeepClone implements Cloneable {
  3. private String name;
  4.  
  5. private Integer age;
  6.  
  7. private List<String> hobbies;
  8.  
  9. @Override
  10. protected Object clone() throws CloneNotSupportedException {
  11. return this.deepClone();
  12. }
  13.  
  14. public UserDto deepClone() {
  15. try {
  16. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  17. ObjectOutputStream oos = new ObjectOutputStream(bos);
  18. oos.writeObject(this);
  19.  
  20. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
  21. ObjectInputStream ois = new ObjectInputStream(bis);
  22. UserDto dto = (UserDto) ois.readObject();
  23. return dto;
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. return null;
  27. }
  28. }
  29. }
  1. public class DeepCloneTest {
  2. public static void main(String[] args) {
  3. DeepCloneTest deepCloneTest = new DeepCloneTest();
  4. UserDeepClone user = new UserDeepClone();
  5. user.setName("皮肤黝黑的小白");
  6. user.setHobbies(new ArrayList<>());
  7. System.out.println(user);
  8. UserDto dto = null;
  9. try {
  10. dto = (UserDto) deepCloneTest.clone();
  11. } catch (CloneNotSupportedException e) {
  12. e.printStackTrace();
  13. }
  14. System.out.println(dto);
  15. System.out.println(user.getName() == dto.getName());
  16. System.out.println(user.getHobbies() == dto.getHobbies());
  17. }
  18. }

4、克隆破坏单例

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

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

  1. public Object clone() {
  2. try {
  3. ArrayList<?> v = (ArrayList<?>) super.clone();
  4. v.elementData = Arrays.copyOf(elementData, size);
  5. v.modCount = 0;
  6. return v;
  7. } catch (CloneNotSupportedException e) {
  8. // this shouldn't happen, since we are Cloneable
  9. throw new InternalError(e);
  10. }
  11. }

  

  

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. 【朝花夕拾】跨进程通信,你只知道AIDL,就OUT了

    一.前言 提起跨进程通信,大多数人首先会想到AIDL.我们知道,用AIDL来实现跨进程通信,需要在客户端和服务端都添加上aidl文件,并在服务端的Service中实现aidl对应的接口.如果还需要服务 ...

  2. Java IO编程——字符流与字节流

    在java.io包里面File类是唯一 一个与文件本身有关的程序处理类,但是File只能够操作文件本身而不能够操作文件的内容,或者说在实际的开发之中IO操作的核心意义在于:输入与输出操作.而对于程序而 ...

  3. java里的单例实现

    枚举实现单例 线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用 public enum SingletonFactory { //枚举元素本身就是单例 INSTANCE; //添加 ...

  4. Vue中Form表单验证无法消除验证问题

    iView的表单api给出了一个resetFields方法,用于重置整个表单输入的内容并清除验证提示. 但是有时候需要只消除部分的iview的resetFields方法源码是这样的resetField ...

  5. 【原创】基于.NET的轻量级高性能 ORM - TZM.XFramework 之优雅增删改

    [前言] 大家好,我是TANZAME.出乎意料的,我们在立冬的前一天又见面了,天气慢慢转凉,朋友们注意添衣保暖,愉快撸码.距离 TZM.XFramework 的首秀已数月有余,期间收到不少朋友的鼓励. ...

  6. 超简单让.NET Core开发者快速拥有CI/CD的能力-Docker版本

    超简单让.NET Core开发者快速拥有CI/CD的能力-Docker版本 前言 上一篇自动化测试,全面且详细的介绍了从零开始到发布版本的步骤,这是传统的方式,本次为大家带来的是如何在5分钟内使用上d ...

  7. Knative Serving 健康检查机制分析

    作者|  阿里云智能事业群技术专家牛秋霖(冬岛) 导读:从头开发一个Serverless引擎并不是一件容易的事情,今天咱们就从Knative的健康检查说起.通过健康检查这一个点来看看Serverles ...

  8. 学习笔记42_SpringMVC

    SpringMVC中,Global.axas发生变化,其中 1.原来是 public class MvcApplication:System.web.HttpApplication 现在是 publi ...

  9. [python]一些常用的python知识总结

    Pthon知识积累,遇到的各种python问题汇总 json.dumps()和json.loads()是json格式处理函数 json.dumps()函数是将一个Python数据类型列表进行json格 ...

  10. [Luogu5384][Cnoi2019] 雪松果树

    传送门 虽然这题是一道二合一,也不算难,但还是学到了很多东西啊,\(k\) 级儿子个数的五种求法!!我还是觉得四种比较好( \(k\) 级儿子个数有五种求法,你知道么? --鲁迅 首先 \(k\) 级 ...