原型模式

spring中的scope=“prototype”,JSON.parseObject()都是一种原型模式。
原型模式适合以下场景:

  1. 类初始化消耗资源较多
  2. new一个对象很麻烦
  3. 构造函数很复杂
  4. 循环体中产生大量对象

浅克隆

标准的原型模式:
接口:

public interface Prototype {
    Prototype clone();
}

需要被克隆的类:

public class ConcretePrototypeA implements Prototype {

    private int age;
    private String name;
    private List<String> hobbies;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public Prototype clone() {
        ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
        concretePrototypeA.setAge(this.age);
        concretePrototypeA.setName(this.name);
        concretePrototypeA.setHobbies(this.hobbies);
        return concretePrototypeA;
    }
}

clinet类:

public class Client {

    private Prototype prototype;

    public Client(Prototype prototype) {
        this.prototype = prototype;
    }

    public Prototype startClone(Prototype prototype){
        return prototype.clone();
    }

}

测试代码:

    @Test
    public void test1() {
        ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
        concretePrototypeA.setAge(18);
        concretePrototypeA.setName("Tom");
        concretePrototypeA.setHobbies(Arrays.asList("hob", "by"));

        // 创建client准备克隆
        Client client = new Client(concretePrototypeA);
        ConcretePrototypeA clone = (ConcretePrototypeA) client.startClone(concretePrototypeA);
        System.out.println("clone = " + clone);
        System.out.println(concretePrototypeA.getHobbies());
        System.out.println(clone.getHobbies());
        System.out.println(concretePrototypeA.getHobbies() == clone.getHobbies());
    }

运行结果不尽人意,引用类型并没有完全克隆,只复制了值类型。

深克隆

用序列化反序列化实现:

@Data
public class Monkey implements Serializable {

    private int height;
    private int weight;
    public Date birthday;

}
@Data
public class JinGuBang implements Serializable {

    private float h = 100;
    private float d = 10;

    public void big() {
        this.d *= 2;
        this.h *= 2;
    }

    public void small(){
        this.d /= 2;
        this.h /= 2;
    }

}
@Data
public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {

    private JinGuBang jinGuBang;

    public QiTianDaSheng() {
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }

    public QiTianDaSheng(JinGuBang jinGuBang) {
        this.jinGuBang = jinGuBang;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }

    public Object 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);
            QiTianDaSheng copy = (QiTianDaSheng) ois.readObject();
            return copy;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

测试:

    @Test
    public void test() throws CloneNotSupportedException {
        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        QiTianDaSheng clone = (QiTianDaSheng) qiTianDaSheng.clone();
        System.out.println("深克隆 "+(qiTianDaSheng==clone));
        System.out.println("深克隆 "+(qiTianDaSheng.getJinGuBang()==clone.getJinGuBang()));
    }

结果:
引用类型指向不同的对象,成功深克隆;

克隆会破坏单例模式

需要放置克隆破坏单例模式,就要重写clone方法,在clone方法里面返回单例对象就可以了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容