1.原型模式测试 == 两种方式,你选哪一种?
package com.zhaoshuangjian.mode05_原型模式; import com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork; import com.zhaoshuangjian.mode05_原型模式.mode05.PupilStudent; import com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum; import com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum; import com.zhaoshuangjian.utils.DateUtils; import java.util.Date; /** * <p>原型模式测试 == 两种方式,你选哪一种?</p> * * @Author zhaoshuangjian 2023-03-23 下午10:39 */ public class PrototypeTest { public static void main(String[] args) throws CloneNotSupportedException{ // 原型 == 我们创建一个已经由小学生【刘晓然】完成的作业对象 HomeWork homeWork = new HomeWork(); // 设置作业信息 homeWork.setType(WorkTypeEnum.WULI); homeWork.setPages(12); homeWork.setFinishTime(new Date()); // 设置小学生信息 == 刘晓然 PupilStudent pupilStudent = new PupilStudent(); pupilStudent.setsNo(1001L); pupilStudent.setName("刘晓然"); pupilStudent.setAge(10); pupilStudent.setSex(SexEnum.FEMALE); pupilStudent.setsClass(4); homeWork.setPupilStudent(pupilStudent); // 1、原型模式第一种 == 作业对象浅拷贝测试 HomeWork ykHomeWork = shallowCopy(homeWork); System.out.println("刘晓然的作业:\n"+homeWork); System.out.println("我的作业:\n"+ykHomeWork); /** * 以上输出结果为: * 刘晓然的作业: * 类型:物理,页数:12,完成时间:2023年03月22日 14时03分45秒,完成者:zhaoshuangjian,学号:1002,年级:4,年龄:10,性别:男 * 我的作业: * 类型:物理,页数:12,完成时间:2023年03月23日 14时03分45秒,完成者:zhaoshuangjian,学号:1002,年级:4,年龄:10,性别:男 * * 纳尼??? * 老师:"刘晓然同学,你说,你作业是不是抄别人的?为什么你的作业和zhaoshuangjian同学的作业一模一样!!!" * 刘晓然:"老师,我自己做的,我没有抄啊,哭哭哭......" * zhaoshuangjian:"我去,这,什么情况?我不是都改了吗,啊啊啊啊啊......" */ // 2、原型模式第二种 == 作业对象深拷贝测试 System.out.println("=========================================分割线========================================="); /** * 假设有第三个同学,要抄作业,这个同学假设叫"张聪明" * 他怎么聪明呢?我们看下面的案列 */ HomeWork zhangHomeWork = deepCopy(ykHomeWork); System.out.println("zhaoshuangjian的作业:\n"+ykHomeWork); System.out.println("张聪明的作业:\n"+zhangHomeWork); /** * 以上输出结果为: * zhaoshuangjian的作业: * 类型:物理,页数:12,完成时间:2023年03月23日 14时16分11秒,完成者:zhaoshuangjian,学号:1002,年级:4,年龄:10,性别:男 * 张聪明的作业: * 类型:物理,页数:12,完成时间:2023年03月23日 14时16分11秒,完成者:张聪明,学号:1003,年级:4,年龄:10,性别:男 * * * 老师:"张聪明同学,你的作业完成的很棒吗!" * 张聪明:"哈哈,果然这种抄作业的方式很完美,完全没有漏洞" * 老师:"刘晓然和zhaoshuangjian,你们俩放学留一下,不讲清楚你俩作业怎么回事,我就叫你们家长过来!" * 刘晓然:"老师,我是真没抄啊,我都不知道发生了什么啊,呜呜呜呜..." * zhaoshuangjian:"卧槽,我再也不干这种伤天害理的事情了,我下一次一定要深度抄作业!!!!" */ } /** * 对象浅拷贝 * @param homeWork * @return * @throws CloneNotSupportedException */ public static HomeWork shallowCopy(HomeWork homeWork) throws CloneNotSupportedException{ /** * 独白: * (1)复制一份【刘晓然】的作业 * (2)将复制过来的作业改成我自己的,记住,信息全改,不然被老师发现了,我还在"三好学生"堆里面怎么混 * (3)我以为自己耍了个小聪明,擅自改作业,却不知"尴尬"却正在发生.... */ HomeWork myHomeWork = homeWork.clone(); // 开始改造 == 首先改完成时间 myHomeWork.setFinishTime(DateUtils.addDays(1)); // 然后改作业的完成者,就是我 == 【zhaoshuangjian】 PupilStudent mySelf = myHomeWork.getPupilStudent(); // 学号肯定不能一样吧,不然这还不被发现作业是抄的吗 mySelf.setsNo(1002L); // 我去,还要改名字,这事我差点忘了 mySelf.setName("zhaoshuangjian"); // 性别,对,还有性别,这个不能粗心大意,忘改了 mySelf.setSex(SexEnum.MALE); // OK,一切就绪,改的那叫一个相当顺利啊,哈哈哈哈! == 满心欢喜交作业咯 return myHomeWork; } /** * 对象深度拷贝 * @param homeWork * @return * @throws CloneNotSupportedException */ public static HomeWork deepCopy(HomeWork homeWork) throws CloneNotSupportedException{ /** * 独白: * (1)复制一份【zhaoshuangjian】的作业 * (2)因为是深度拷贝,抄的比较认真,比较深,雪下的那么认真..... * (3)因此,我完全不必担心,老师会发现端倪,哈哈哈哈哈哈..... */ HomeWork myHomeWork = homeWork.deepClone(); // 开始改造 == 首先改完成时间,完成时间+1天 myHomeWork.setFinishTime(DateUtils.addDays(1)); PupilStudent mySelf = myHomeWork.getPupilStudent(); mySelf.setsNo(1003L); mySelf.setName("张聪明"); mySelf.setSex(SexEnum.MALE); return myHomeWork; } }
2.小学生的家庭作业
package com.zhaoshuangjian.mode05_原型模式.mode05; import com.zhaoshuangjian.utils.DateUtils; import com.fasterxml.jackson.annotation.JsonFormat; import java.io.*; import java.util.Date; /** * <p>小学生的家庭作业</p> * * @Author zhaoshuangjian 2023-03-23 下午10:39 */ public class HomeWork implements Cloneable,Serializable { private static final long serialVersionUID = 1L; /** * 作业类型 */ private com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum type = com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum.YUWEN; /** * 完成时间 */ @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") private Date finishTime ; /** * 作业页码数【作业量】 */ private Integer pages = 0; /** * 完成者 */ private com.zhaoshuangjian.mode05_原型模式.mode05.PupilStudent pupilStudent; public HomeWork(){ } public com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum getType() { return type; } public void setType(com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum type) { this.type = type; } public Date getFinishTime() { return finishTime; } public void setFinishTime(Date finishTime) { this.finishTime = finishTime; } public Integer getPages() { return pages; } public void setPages(Integer pages) { this.pages = pages; } public com.zhaoshuangjian.mode05_原型模式.mode05.PupilStudent getPupilStudent() { return pupilStudent; } public void setPupilStudent(com.zhaoshuangjian.mode05_原型模式.mode05.PupilStudent pupilStudent) { this.pupilStudent = pupilStudent; } /** * 对象浅拷贝 == 对象中按值类型传递部分均能完美拷贝走,但是按引用类型传递部分则拷贝不走 * @return * @throws CloneNotSupportedException */ @Override public com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork clone() throws CloneNotSupportedException { return (com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork) super.clone(); } /** * 深度拷贝 == 不管你对象中是值类型部分,还是引用类型部分,我全部拿走 * 对象字节流的序列与反序列化 ==> 对象完全、深度、彻彻底底的Copy!!! * @return */ public com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork deepClone(){ // Anything 都是可以用字节流进行表示,记住是任何! com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork homeWork = null; try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); // 将当前的对象写入baos【输出流 -- 字节数组】里 oos.writeObject(this); // 从输出字节数组缓存区中拿到字节流 byte[] bytes = baos.toByteArray(); // 创建一个输入字节数组缓冲区 ByteArrayInputStream bais = new ByteArrayInputStream(bytes); // 创建一个对象输入流 ObjectInputStream ois = new ObjectInputStream(bais); // 下面将反序列化字节流 == 重新开辟一块空间存放反序列化后的对象 homeWork = (com.zhaoshuangjian.mode05_原型模式.mode05.HomeWork) ois.readObject(); }catch (Exception e){ System.out.println(e.getClass()+":"+e.getMessage()); } return homeWork; } @Override public String toString() { return String.format("类型:%s,页数:%s,完成时间:%s," + "完成者:%s,学号:%d,年级:%d,年龄:%d,性别:%s",this.type.getName() ,this.pages,DateUtils.dateTostring(this.finishTime),this.pupilStudent.getName(), this.pupilStudent.getsNo(),this.pupilStudent.getsClass(), this.pupilStudent.getAge(),this.pupilStudent.getSex().getName()); } }
3.小学生 == 如果要实现对象的深度拷贝,嵌套引用类型的对象类必须也实现Serializable接口
package com.zhaoshuangjian.mode05_原型模式.mode05; import java.io.Serializable; /** * <p>小学生 == 如果要实现对象的深度拷贝,嵌套引用类型的对象类必须也实现Serializable接口</p> * * @Author zhaoshuangjian 2023-03-23 下午10:39 */ public class PupilStudent implements Serializable { private static final long serialVersionUID = 1L; /** * 学号 */ private Long sNo; /** * 年级 */ private Integer sClass; /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; /** * 性别 */ private SexEnum sex = SexEnum.MALE; public PupilStudent(){ } public Long getsNo() { return sNo; } public void setsNo(Long sNo) { this.sNo = sNo; } public Integer getsClass() { return sClass; } public void setsClass(Integer sClass) { this.sClass = sClass; } 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 SexEnum getSex() { return sex; } public void setSex(SexEnum sex) { this.sex = sex; } }
4.性别枚举类
package com.zhaoshuangjian.mode05_原型模式.mode05; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; /** * <p>性别枚举类</p> * * @Author zhaoshuangjian 2023-03-23 下午10:39 */ public enum SexEnum { /** * 枚举对象 */ MALE("男",0), FEMALE("女",1); private final String name ; private final Integer value; /** * 枚举构造器 * @param name 性别名称 * @param value 性别值 */ SexEnum(String name,Integer value){ this.name = name; this.value = value; } /** * 通过name获取对应的枚举对象 * @param name 类型名称 * @return */ public static com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum getEnum(String name){ for(com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum sexEnum : com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum.values()){ if(name.equals(sexEnum.getName())){ return sexEnum; } } return null; } /** * 通过value获取对应的枚举对象 * @param value 类型值 * @return */ @JsonCreator public static com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum getEnum(Integer value){ for(com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum sexEnum : com.zhaoshuangjian.mode05_原型模式.mode05.SexEnum.values()){ if(value.equals(sexEnum.getValue())){ return sexEnum; } } return null; } public String getName() { return name; } @JsonValue public Integer getValue() { return value; } }
5.作业枚举类
package com.zhaoshuangjian.mode05_原型模式.mode05; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; /** * <p>作业枚举类</p> * * @Author zhaoshuangjian 2023-03-23 下午10:39 */ public enum WorkTypeEnum { /** * 枚举对象 */ YUWEN("语文",0), SHUXUE("数学",1), YINGYU("英语",2), WULI("物理",3), HUAXUE("化学",4), SHENGWU("生物",5); private final String name ; private final Integer value; /** * 枚举构造器 * @param name 作业类型名称 * @param value 作业类型值 */ WorkTypeEnum(String name,Integer value){ this.name = name; this.value = value; } /** * 通过name获取对应的枚举对象 * @param name 类型名称 * @return */ public static com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum getEnum(String name){ for(com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum typeEnum : com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum.values()){ if(name.equals(typeEnum.getName())){ return typeEnum; } } return null; } /** * 通过value获取对应的枚举对象 * @param value 类型值 * @return */ @JsonCreator public static com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum getEnum(Integer value){ for(com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum typeEnum : com.zhaoshuangjian.mode05_原型模式.mode05.WorkTypeEnum.values()){ if(value.equals(typeEnum.getValue())){ return typeEnum; } } return null; } public String getName() { return name; } @JsonValue public Integer getValue() { return value; } }