设计模式---原型模式(Prototype)

来源:互联网 发布:我的邻居是exo网络剧 编辑:程序博客网 时间:2024/05/17 07:04

这个模式我看最早的一个版本的时候,我也没看懂,后来我换了一篇文章才看明白


先写一个简历类

//简历类public class Resume {    //定义简历类需要的属性    private String name;    private String sex;    private String age;    private String workTime;    private String company;    public Resume(String name) {        this.name = name;    }    public void personalInfo(String sex, String age) {        this.sex = sex;        this.age = age;    }    public void workExperience(String workTime, String company) {        this.workTime = workTime;        this.company = company;    }    public void show() {        System.out.println(name);        System.out.println(age + "---" + sex);        System.out.println(company + "---" + workTime);    }}

调用简历类生成实体对象

public class Main {    public static void main(String[] args) {        //第一个版本调用方式        //比如说我要打印三分简历,我最原始的方法是这么做        Resume resume1 = new Resume("小鱼");        resume1.personalInfo("男","18");        resume1.workExperience("2006-2010","北京科技大学");        resume1.show();        Resume resume2 = new Resume("小鱼");        resume2.personalInfo("男","18");        resume2.workExperience("2006-2010","北京科技大学");        resume2.show();        Resume resume3 = new Resume("小鱼");        resume3.personalInfo("男","18");        resume3.workExperience("2006-2010","北京科技大学");        resume3.show();        System.out.println(resume1.equals(resume2));//false        System.out.println(resume2.equals(resume3));//false        //我稍微进步点的方法,我可能会这么做        Resume resumeA = new Resume("小鱼");        resumeA.personalInfo("男","18");        resumeA.workExperience("2006-2010","北京科技大学");        resumeA.show();        Resume resumeB = resumeA;//        resumeB.personalInfo("男","18");//        resumeB.workExperience("2006-2010","北京科技大学");        resumeB.show();        Resume resumeC = resumeA;        resumeC.personalInfo("男","22岁");        resumeC.workExperience("2010-2013","清华大学");        resumeC.show();        resumeA.show();        System.out.println(resumeA.equals(resumeB));//true        System.out.println(resumeB.equals(resumeC));//true    }}

输出结果:
小鱼18---男北京科技大学---2006-2010小鱼18---男北京科技大学---2006-2010小鱼18---男北京科技大学---2006-2010falsefalse小鱼18---男北京科技大学---2006-2010小鱼18---男北京科技大学---2006-2010小鱼22岁---男清华大学---2010-2013小鱼22岁---男清华大学---2010-2013truetrue

从输出结果可以看出,由于三分简历引用的是同一个对象,导致我改简历C的时候,改变了简历A,因为他们引用是相同的嘛,指向地址相同。

为了避免这个问题的发生,我对简历类做了一些改造

//简历类    //实现接口Cloneable,这个接口叫标记接口,接口里啥都没定义。public class Resume implements Cloneable {    //定义简历类需要的属性    private String name;    private String sex;    private String age;    private String workTime;    private String company;    public Resume(String name) {        this.name = name;    }    public void personalInfo(String sex, String age) {        this.sex = sex;        this.age = age;    }    public void workExperience(String workTime, String company) {        this.workTime = workTime;        this.company = company;    }    public void show() {        System.out.println(name);        System.out.println(age + "---" + sex);        System.out.println(company + "---" + workTime);    }    public Resume createClone() throws CloneNotSupportedException {        return (Resume) clone();    }}
然后运行,并看结果
public class Main {    public static void main(String[] args) {        Resume resumeA = new Resume("小王");        resumeA.personalInfo("男", "18");        resumeA.workExperience("2006-2010", "微软中国");        resumeA.show();        try {            Resume cloneA1 = resumeA.createClone();            cloneA1.personalInfo("爷们", "23");            cloneA1.show();            Resume cloneA2 = resumeA.createClone();            cloneA2.workExperience("2050-2055","宇宙编程公司");            cloneA2.show();            resumeA.show();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }    }}
从下面的输出结果可以发现简历A没有受到影响
小王18---男微软中国---2006-2010小王23---爷们微软中国---2006-2010小王18---男宇宙编程公司---2050-2055小王18---男微软中国---2006-2010
这里为什么会有异常我们暂且先不讨论,后面我会说明这个异常。

但是有一天我的需求又改了,我简历类的公司相关的内容要单独提取出来作为一个类存在
于是我将简历类改为如下两个类
package com.domain;public class Resume implements Cloneable {    private String name;    private String sex;    private String age;    private WorkExperience workExperience;    public Resume(String name) {        this.name = name;    }    public void personalInfo(String sex, String age) {        this.sex = sex;        this.age = age;    }    public void workExperience(WorkExperience workExperience) {        this.workExperience = workExperience;    }    public Resume createClone() throws CloneNotSupportedException {        return (Resume) clone();    }    public void show() {        System.out.println(name + "---" + sex + "---" + age+"---" + workExperience.getWorkTime() + "---" + workExperience.getCompany());    }    public WorkExperience getWorkExperience() {        return workExperience;    }    public void setWorkExperience(WorkExperience workExperience) {        this.workExperience = workExperience;    }}
package com.domain;public class WorkExperience {    private String workTime;    private String company;    public WorkExperience(String workTime, String company) {        this.workTime = workTime;        this.company = company;    }    public String getWorkTime() {        return workTime;    }    public void setWorkTime(String workTime) {        this.workTime = workTime;    }    public String getCompany() {        return company;    }    public void setCompany(String company) {        this.company = company;    }}
然后我运行,打印,发现问题
package com;import com.domain.Resume;import com.domain.WorkExperience;public class Main {    public static void main(String[] args) {        Resume resume = new Resume("明明");        resume.personalInfo("男", "22");        resume.workExperience(new WorkExperience("2000", "百度"));        resume.show();        try {            Resume clone = resume.createClone();            clone.show();            resume.getWorkExperience().setWorkTime("2022");            resume.getWorkExperience().setCompany("新浪");            resume.personalInfo("女", "40");            resume.show();            clone.show();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }    }}
明明---男---22---2000---百度明明---男---22---2000---百度明明---女---40---2022---新浪明明---男---22---2022---新浪
产生这个现象的原因很明了了,因为clone()方法在复制基本类型的时候,复制的是值,
而复制引用类型的时候,复制的是地址值,被复制的对象的地址值还是指向原地址
这也就是我们常说的浅复制!!!
比如说数据集对象,DataSet()他就有clone()方法和copy()方法分别实现了浅复制和深复制。






















原创粉丝点击