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

xiaoxiao2021-02-28  69

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

先写一个简历类

//简历类 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-2010 false false 小鱼 18---男 北京科技大学---2006-2010 小鱼 18---男 北京科技大学---2006-2010 小鱼 22岁---男 清华大学---2010-2013 小鱼 22岁---男 清华大学---2010-2013 true true 从输出结果可以看出,由于三分简历引用的是同一个对象,导致我改简历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()方法分别实现了浅复制和深复制。

转载请注明原文地址: https://www.6miu.com/read-71655.html

最新回复(0)