美文网首页
原型模式和深拷贝、浅拷贝

原型模式和深拷贝、浅拷贝

作者: pepsi1000 | 来源:发表于2019-08-08 15:46 被阅读0次

    1. PROS&CONS

    PROS

    • 对象拷贝比new实例性能高
    • 简化创建过程

    这是因为对象拷贝的过程时,不会调用构造器,通过实现Cloneable接口并调用Object.clone实现对象拷贝。

    CONS

    • 必须重写Object.clone
    • 复杂对象进行对象拷贝的风险大,涉及深拷贝,浅拷贝问题

    2. 适用场景

    • 类初始化消耗较多资源,循环体生产大量对象时
    • new一个对象过程繁琐,构造函数负债

    3. 浅拷贝&深拷贝

    浅拷贝

    @Setter
    @Getter
    public class User implements Cloneable {
        private String id;
        private String username;
        private Date birthday;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id='" + id + '\'' +
                    ", username='" + username + '\'' +
                    ", birthday=" + birthday +
                    '}' + super.toString();
        }
    }
    
    

    user1通过对象拷贝获得user2实例对象,但是user2中的birthday和user1中的birthday指向都了堆中的同一个Date实例对象,即相同引用,属于浅拷贝。这样会导致无论是在user1修改了birthday还是user2修改,birthday都会发生变化。

    public static void main(String[] args) throws CloneNotSupportedException {
            Date date1 = new Date(1L);
            User user1 = new User();
            user1.setBirthday(date1);
            User user2 = (User) user1.clone();
            log.info("{}", user1);
            log.info("{}", user2);
    
            user2.getBirthday().setTime(new Date().getTime());
            log.info("{}", user1);
            log.info("{}", user2);
        }
    

    深拷贝

    如何实现深拷贝?通过重现User类的clone方法。

     @Override
        protected Object clone() throws CloneNotSupportedException {
            User user = (User) super.clone();
    
            // 深克隆
            user.birthday = (Date) user.getBirthday().clone();
            return user;
        }
    

    4. 原型模式破坏单例模式

    HungrySingleton hungrySingleton = HungrySingleton.getInstance();
    Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
    method.setAccessible(true);
    HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton, null);
    log.info("{}", hungrySingleton);
    log.info("{}", cloneHungrySingleton);
    

    如何解决?

    1. 单例类不实现Cloneable
    2. clone方法返回原单例对象
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return getInstance();
    }
    

    5. 源码案例

    • ArrayList
    • HashMap
    • Mybatis#CacheKey

    相关文章

      网友评论

          本文标题:原型模式和深拷贝、浅拷贝

          本文链接:https://www.haomeiwen.com/subject/rzvxjctx.html