zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    复制代码

    转载于:https://www.cnblogs.com/xcgShare/p/11961799.html

  • 相关阅读:
    人工智能背后的故事
    idea 开发插件。
    安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify Chinesization cool decoration
    安卓工作室 android studio文件和代码模板,以及汉化出错问题
    安卓工作室 android studio 汉化后,报错。 设置界面打不开。Can't find resource for bundle java.util.PropertyResourceBundle, key emmet.bem.class.name.element.separator.label
    android studio的汉化 教程 及解析
    安卓工作室Android Studio 快捷键
    安卓工作室 android studio 的 汉化 美化 定制 Android studio's Chinesization beautification customization
    VR开发 VR development
    Lakeshore 中文开发界面,示例项目,飞机大战 等 Lakeshore Chinese development interface, sample project, aircraft war, etc
  • 原文地址:https://www.cnblogs.com/it-deepinmind/p/13224179.html
Copyright © 2011-2022 走看看