Design Pattern [4] —— 原型模式 Prototype
原型模式==》对象的克隆
优点:
- 克隆对象会将对象已经设置的属性带出来,而不用在new之后去一个个重新设置。
- Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
看源码,clone() 前面有native修饰,本地方法,说明最终调用了C++
我的Github里有源码,可以clone下来自己跑下:https://github.com/Yang2199/Design-Pattern/tree/master/src
例子:
import lombok.*;
import java.util.Date;
//@Data // Lombok的@Data注解有侵入性,会重写hashcode,导致clone对象hash值一致
@AllArgsConstructor
@Setter
@Getter
public class Video implements Cloneable{ //implements Cloneable
private String name;
private Date createTime;
@Override
public String toString() { //手动增加打印hashcode
return "hashCode = " + super.hashCode() +
" Video{" +
" name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
//Alt+Insert => Override =>clone()
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//父类克隆
}
}
测试:
import java.util.Date;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {
Date date = new Date();
Video video1 = new Video("【流浪地球】", date);
System.out.println("video1 = " + video1);
Video video2 = (Video) video1.clone(); //类型强制转换
System.out.println("video2 = " + video2);
video2.setName("【学习视频】");
System.out.println("video1 = " + video1);
System.out.println("video2 = " + video2);
}
}
结果:
分析:
clone出来的对象的hashCode和原对象是不同的;
修改属性后,两个对象就不同了,说明不是引用,而是真实复制了副本;
加入自定义类:
网上说要重写自定义类的clone(),但我自己试的时候发现不用重写就ok了。。
import lombok.*;
@AllArgsConstructor
@Getter
@Setter
public class ClonePeople implements Cloneable{
private String name;
private Integer height;
private Integer Intelligent;
private BaseInfo baseInfo;//自定义类
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "hashCode" + super.hashCode() +
" ClonePeople{" +
"name='" + name + '\'' +
", height=" + height +
", Intelligent=" + Intelligent +
", baseInfo=" + baseInfo +
'}';
}
}
写一个自定义类:
import lombok.*;
@Setter
@Getter
@AllArgsConstructor
@ToString
public class BaseInfo {
private String address;
private String parents;
}
测试:
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
ClonePeople clonePeople = new ClonePeople("双胞胎哥哥",195,155, new BaseInfo("地球","超人"));
//有参构造中,对象的值格式(value1 , value2) =>括号逗号
System.out.println("OriginPeople = " + clonePeople);//这里clonePeople等价于clonePeople.toString()
// System.out.println("clonePeople = " + clonePeople.toString());
ClonePeople cloneLittleBrother = (ClonePeople) clonePeople.clone();//纯克隆,只有hashCode改变
System.out.println("clone = " + cloneLittleBrother);
//设置新属性值
cloneLittleBrother.setName("双胞胎弟弟");
cloneLittleBrother.setIntelligent(175);
cloneLittleBrother.setBaseInfo(new BaseInfo("海王星","超人"));
System.out.println("======最终结果======");
System.out.println("cloneLittleBrother = " + cloneLittleBrother);
System.out.println("OriginPeople = " + clonePeople.toString());
}
}
结果: