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

原型模式与深浅拷贝

作者: 台风口的猪 | 来源:发表于2019-11-19 15:12 被阅读0次

使用原型实例指定将要创建的对象类型,通过复制这个实例创建(新的对象)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Date;

/**
 * @desc 需要多份简历投送到不同公司
 */

@Data
@Slf4j
public class Resume implements Cloneable, Serializable {

    private String name;
    private int age;
    private Date resumeDate;
    private JobExperience jobExperience;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class JobExperience implements Serializable {
        private Integer salary;
        private String duty;
    }

    public Resume() {
        this.name = "xzz";
        this.age = 15;
        this.resumeDate = new Date();
        this.jobExperience = new JobExperience(19900, "喝酒");
        log.info("-----------resume构造方法-------------");
    }


    /**
     * 浅clone 八大基本数据类型和String(默认浅克隆)
     * 直接将原对象中的jobExperience的引用值拷贝给新对象的jobExperience字段
     *
     * @return
     */
    public Resume shallowClone() {
        try {
            return (Resume) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 深clone
     * 根据原Resume对象中的jobExperience指向的对象创建一个新的相同的对象,
     * 将这个新对象的引用赋给新拷贝的Resume对象的jobExperience字段
     */
    public Resume deepClone() {
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            // 序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            // 反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Resume resume = (Resume) ois.readObject();
            resume.setResumeDate(new Date());
            resume.setJobExperience(new JobExperience(18000, "发呆"));
            return resume;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bos.close();
                oos.close();

                bis.close();
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * TODO 原型模式的要求是需要clone出来的对象是不同的实例
     * 如果使用shallowClone()方法那么 (this.jobExperience==clone.jobExperience) is true
     * 因为shallowClone()是浅拷贝,浅拷贝直接将原对象中的jobExperience的引用值拷贝给新对象的jobExperience字段(拷贝引用)
     * 如果使用deepClone()方法那么 (this.jobExperience==clone.jobExperience) is false
     * 因为deepClone()是深拷贝,深拷贝是先根据原对象Resume中的jobExperience的指向创建一个新的对象,然后赋值给新拷贝的Resume对象中的jobExperience
     */
    public void resumeShallow() {
        Resume clone = shallowClone();
        log.info("resume 与 clone resume:{}为false则表示两个对象相互独立", (this == clone));
        log.info("job time: this:{},clone:{}", this.resumeDate.getTime(), clone.getResumeDate().getTime());
        //  ==比较的就是两个对象的引用是否相同,引用相同那么就是同一个实例,则不满足原型模式的要求
        log.info("jobExperience如果为true表示持有相同引用:{}", (this.jobExperience == clone.jobExperience));
        log.info("基本类型int深浅拷贝:{}", this.getAge() == clone.getAge());
        log.info("String类型深浅拷贝:{}", this.getName() == clone.getName());
        log.info("resume:{}   \r\n   clone resume:{}", this.toString(), clone.toString());
    }

    public void resumeDeep() {
        Resume clone = deepClone();
        log.info("resume 与 clone resume为false则表示两个对象相互独立:{}", (this == clone));
        log.info("job time: this:{},clone:{}", this.resumeDate.getTime(), clone.getResumeDate().getTime());
        log.info("jobExperience如果为true表示持有相同引用:{}", (this.jobExperience == clone.jobExperience));
        log.info("基本类型int深浅拷贝:{}", this.getAge() == clone.getAge());
        log.info("String类型深浅拷贝:{}", this.getName() == clone.getName());
        log.info("resume:{}   \r\n   clone resume:{}", this.toString(), clone.toString());
    }


    @Override
    public String toString() {
        return "Resume{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", resumeDate=" + resumeDate +
                ", jobExperience=" + jobExperience +
                '}';
    }
}



public class ResumeTest {

    public static void main(String[] args) {
        Resume resume = new Resume();
        resume.resumes();
    }
}

clone是字节码复制(所以性能比较好)

注意事项:

  1.不需要调用对象的构造方法
  2.原型模式与单例模式有冲突,
  3.浅拷贝并不适合与原型模式中使用,更多情况下我们需要一个不会影响原始对象的一个新对象,也就需要使用深拷贝,

总结

原型模式的本质就是clone,可以解决构建复杂对象的资源消耗问题,可以返回一个对象的拷贝,从而保护原对象(多用于只读)

clone参考链接:https://blog.csdn.net/zhangjg_blog/article/details/18369201/

相关文章

  • 原型模式与深浅拷贝

    使用原型实例指定将要创建的对象类型,通过复制这个实例创建(新的对象) clone是字节码复制(所以性能比较好) 注...

  • 原型模式

    一、 原型模式 原型模式:用原型实指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 涉及浅拷贝与深拷贝问题。...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • 原型模式及深浅拷贝详解

    原型模式 原型模式(Prototype模式)是用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。 ...

  • 设计模式之原型模式(Prototype)

    1. 什么是原型模式? 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象 简单来说, 原型模式就是拷贝...

  • 设计模式之原型模式,及深浅拷贝

    设计模式,不管是在准备面试过程,还是在实际工作编码中,都是应该掌握的技能,所以特别整理一下设计模式相关的知识,希望...

  • 设计模式系列-原型模式,备忘录模式

    原型模式 定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式已经与Java融为一体...

  • 设计模式之原型模式

    原型模式 原型模式(prototype)是指原型实例指向对象的种类,并且通过拷贝这些原型创建新的对象 模式作用: ...

  • 创建型模式5-原型模式

    创建型模式5-原型模式 原型模式(prototype) 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创...

  • 原型模式C++

    原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 原型模式结构图 原型模式基本代码 原型...

网友评论

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

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