• 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

  • 相关阅读:
    UVa 839 Not so Mobile
    UVa 548 Tree(中序遍历+后序遍历)
    UVa-679 Dropping Balls(二叉树的编号)
    Vue练习三十一:04_04_arguments应用_求出参数的和
    Vue练习三十:04_03_自动改变方向播放_幻灯片效果
    Vue练习二十九:04_02_自动播放_幻灯片效果
    Vue练习二十八:04_01_transition应用(未完成)
    Vue练习二十七:03_09_倒计时时钟
    Vue练习二十六:03_08_简易网页时钟
    Vue练习二十五:03_07_网页计算器
  • 原文地址:https://www.cnblogs.com/it-deepinmind/p/13224179.html
Copyright © 2020-2023  润新知