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);
            }
        }

      

      

  • 相关阅读:
    反转字符串(指定子串不反转)
    字符串相同字符个数统计
    指针函数/回调函数
    simplest_dll 最简dll的创建与隐式调用(显式调用太麻烦,个人不建议使用)
    字符串的相关操作
    sizeof()函数求各类型变量所占空间的方法
    对于数组使用sizeof(a)和使用sizeof(a[0])
    交换两个数的三种方法
    最简字符串查找操作(静态顺序串,非链串)
    类模板 template<class T>
  • 原文地址:https://www.cnblogs.com/xcgShare/p/11961799.html
Copyright © 2011-2022 走看看