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

2019-08-08  本文已影响0人  pepsi1000

1. PROS&CONS

PROS

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

CONS

2. 适用场景

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. 源码案例

上一篇下一篇

猜你喜欢

热点阅读