设计模式之原型模式

克隆对象

  • 概念
  • 浅复制和深复制
  • 类图
  • 代码实例

概念

原型模式就是我们常常接触的克隆,为了更高效更快的创建对象,无须再进行通过new来创建对象并初始化对象数据,直接通过拷贝内存的对象结构(浅复制),拷贝对象结构和数据(深度复制)进行创建对象。
科普下,记得之前面试的时候被问知道那些创建对象的方式:

1、new 构造方法进行创建
2、反序列化方式
3、clone克隆
4、反射,cls.getConstructor().newInstance() 如果构造方法有参数 cls.getConstructor(Class type).newInstance(具体对应类型参数值)

浅复制和深复制

浅复制:复制对象数据结构,仅仅拷贝对象引用,也就是所有克隆对象中的引用类型的属性都会指向同个对象

深度复制:复制对象结构和数据(并不仅仅拷贝对象引用,而且还要重新clone引用的对象)
注意需要考虑是否有循环引用的问题,假如类A包含类B 类B包含类C 而类C又包含类A 所以这样就是循环引用,如果这个要深复制就会导致clone方法一直被调用直到栈溢出

类图

在这里插入图片描述

代码实例

WorkExperience 工作经历类

/**
 * @author duanyimiao
 * @create 2018-09-23 4:51 PM
 * @description 工作经验类
 **/
public class WorkExperience implements Cloneable {
    private String company;
    private String timeSpan;

    public WorkExperience() {
    }

    public WorkExperience(String company, String timeSpan) {
        this.company = company;
        this.timeSpan = timeSpan;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getTimeSpan() {
        return timeSpan;
    }

    public void setTimeSpan(String timeSpan) {
        this.timeSpan = timeSpan;
    }

    @Override
    public String toString() {
        return "WorkExperience{" +
                "company='" + company + '\'' +
                ", timeSpan='" + timeSpan + '\'' +
                '}';
    }
    @Override
    public Object clone(){
        try {
            return super.clone();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

ResumeByShallowCopy 浅复制的简历类

/**
 * @author duanyimiao
 * @create 2018-09-23 4:50 PM
 * @description 简历类 浅复制 复制对象数据结构
 **/
public class ResumeByShallowCopy implements Cloneable {
    private String name;
    private Integer age;
    private WorkExperience workExperience;

    public ResumeByShallowCopy() {
    }

    public ResumeByShallowCopy(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public WorkExperience getWorkExperience() {
        return workExperience;
    }

    public void setWorkExperience(WorkExperience workExperience) {
        this.workExperience = workExperience;
    }

    @Override
    public String toString() {
        return "ResumeByShallowCopy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", workExperience=" + workExperience +
                '}';
    }

    /**
     * clone方法是在Object类中
     * 该类必须实现Cloneable接口,否则调用此方法会抛出CloneNotSupportedException异常
     * @return
     */
    @Override
    public Object clone(){
        try {
            return super.clone();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

ResumeByDeepCopy 深复制简历类

/**
 * @author duanyimiao
 * @create 2018-09-23 4:50 PM
 * @description 简历类 深度克隆 复制对象结构和数据(并不仅仅拷贝对象引用,而且还要重新clone引用的对象)
 **/
public class ResumeByDeepCopy implements Cloneable {
    private String name;
    private Integer age;
    private WorkExperience workExperience;

    public ResumeByDeepCopy() {
    }

    public ResumeByDeepCopy(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public WorkExperience getWorkExperience() {
        return workExperience;
    }

    public void setWorkExperience(WorkExperience workExperience) {
        this.workExperience = workExperience;
    }

    @Override
    public String toString() {
        return "ResumeByDeepCopy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", workExperience=" + workExperience +
                '}';
    }

    /**
     * 深度复制,注意需要考虑是否有循环引用的问题,假如类A包含类B 类B包含类C 而类C又包含类A 所以这样就是循环引用,如果这个要深复制就会导致clone方法一直被调用直到栈溢出
     *
     * @return
     */
    @Override
    public Object clone() {
        ResumeByDeepCopy resumeByDeepCopy = new ResumeByDeepCopy();
        resumeByDeepCopy.age = this.age;
        resumeByDeepCopy.name = this.name;
        resumeByDeepCopy.workExperience = (WorkExperience) this.workExperience.clone();
        return resumeByDeepCopy;
    }
}

MainTest client测试类

/**
 * @author duanyimiao
 * @create 2018-09-23 4:54 PM
 * @description
 **/
public class MainTest {
    public static void main(String[] args) {
        //不用多次new 就可以打印多份相同的简历,此时为浅复制,也就是简历A 简历B 简历C的工作经历都是一样的,如果我想改动C简历的工作经历时,同时A和B的工作经历都会改变,这并不是我们想要的,这个就需要使用深度克隆了
        System.out.println("=========浅复制");
        ResumeByShallowCopy A = new ResumeByShallowCopy("dynamo");
        A.setAge(18);
        WorkExperience workExperience = new WorkExperience("alibaba", "2016-now");
        A.setWorkExperience(workExperience);
        ResumeByShallowCopy B = (ResumeByShallowCopy) A.clone();
        ResumeByShallowCopy C = (ResumeByShallowCopy) A.clone();

        System.out.println("A address=" + A.hashCode() + " " + "B address=" + B.hashCode() + " " + "C address=" + C.hashCode());
        System.out.println("shallow copy Resume A=" + A);
        System.out.println("shallow copy Resume B=" + B);
        System.out.println("shallow copy Resume C=" + C);
        //想修改简历C的工作经历信息
        C.getWorkExperience().setTimeSpan("2016-2019");

        System.out.println("shallow copy after modify workexperience Resume A=" + A);
        System.out.println("shallow copy after modify workexperience Resume B=" + B);
        System.out.println("shallow copy after modify workexperience Resume C=" + C);

        //深度复制
        System.out.println("=========深复制");
        ResumeByDeepCopy A1 = new ResumeByDeepCopy("dynamo");
        A1.setAge(18);
        WorkExperience workExperience1 = new WorkExperience("alibaba", "2016-now");
        A1.setWorkExperience(workExperience1);
        ResumeByDeepCopy B1 = (ResumeByDeepCopy) A1.clone();
        ResumeByDeepCopy C1 = (ResumeByDeepCopy) A1.clone();

        System.out.println("A1 address=" + A1.hashCode() + " " + "B1 address=" + B1.hashCode() + " " + "C1 address=" + C1.hashCode());
        System.out.println("deep copy Resume A1=" + A1);
        System.out.println("deep copy Resume B1=" + B1);
        System.out.println("deep copy Resume C1=" + C1);
        //想修改简历C的工作经历信息
        C1.getWorkExperience().setTimeSpan("2016-2019");

        System.out.println("deep copy after modify workexperience Resume A1=" + A1);
        System.out.println("deep copy after modify workexperience Resume B1=" + B1);
        System.out.println("deep copy after modify workexperience Resume C1=" + C1);

    }
}

输出结果:

=========浅复制
A address=960687909 B address=1499628417 C address=1386723327
shallow copy Resume A=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy Resume B=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy Resume C=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy after modify workexperience Resume A=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
shallow copy after modify workexperience Resume B=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
shallow copy after modify workexperience Resume C=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
=========深复制
A1 address=1868041274 B1 address=2106256625 C1 address=734659227
deep copy Resume A1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy Resume B1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy Resume C1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume A1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume B1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume C1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值