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;
/**
* 原型模式测试 == 两种方式,你选哪一种?
*
* @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;
}
}
package com.zhaoshuangjian.mode05_原型模式.mode05;
import com.zhaoshuangjian.utils.DateUtils;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.*;
import java.util.Date;
/**
* 小学生的家庭作业
*
* @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());
}
}
package com.zhaoshuangjian.mode05_原型模式.mode05;
import java.io.Serializable;
/**
* 小学生 == 如果要实现对象的深度拷贝,嵌套引用类型的对象类必须也实现Serializable接口
*
* @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;
}
}
package com.zhaoshuangjian.mode05_原型模式.mode05;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* 性别枚举类
*
* @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;
}
}
package com.zhaoshuangjian.mode05_原型模式.mode05;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* 作业枚举类
*
* @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;
}
}