场景:
写好多份简历
初步实现:
工作经历类:
package Prototype;
import java.io.Serializable;
public class workExperience implements Serializable {
private String workdate;
private String workCompany;
public String getWorkdate() {
return workdate;
}
public workExperience setWorkdate(String workdate) {
this.workdate = workdate;
return this;
}
public String getWorkCompany() {
return workCompany;
}
public workExperience setWorkCompany(String workCompany) {
this.workCompany = workCompany;
return this;
}
}
Resume类:
package Prototype;
import java.io.*;
import java.nio.file.Watchable;
public class Resume implements Cloneable, Serializable {
private String name;
private String gender;
private int age;
private workExperience we;
public Resume(){
we = new workExperience();
}
public void display(){
System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public workExperience getWorkExperience(){
return we;
}
public void setWorkExperience(String workDate,String workCompany){
we.setWorkdate(workDate);
we.setWorkCompany(workCompany);
}
public Object deepClone() throws Exception{
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
客户端:
package Prototype;
public class MainTest {
public static void main(String[] args) {
Resume a= new Resume();
a.setName("a");
a.setAge(18);
a.setGender("女");
a.setWorkExperience("2008-2015","xx");
Resume b = new Resume();
b.setName("a");
b.setAge(18);
b.setGender("女");
b.setWorkExperience("2008-2015","xx");
a.display();
b.display();
}
}
但这样的客户端是很麻烦的,每次都需要实例化,如果写错一个字,每次都需要改
如果改成下面这种:
这是在传引用,而不是传值,这样做就如同在b纸张和c纸张上写着:简历在a处一样,没有实际内容。所以应该用clone的方法
clone分为深拷贝和浅拷贝,其实现方式是通过调用Object类的clone方法来完成。在Obiect.class类中,源码为:
protected native Object clone() throws CloneNotSupportedException;
Java 将内存空间分为堆和栈。基本类型直接在栈中存储数值,而引用类型是将引用放在栈中,实际存储的值是放在堆中,通过栈中的引用指向堆中存放的数据。
上图定义的 a 和 b 都是基本类型,其值是直接存放在栈中的;而 c 和 d 是 String 声明的,这是一个引用类型,引用地址是存放在 栈中,然后指向堆的内存空间。
d = c;这条语句表示将 c 的引用赋值给 d,那么 c 和 d 将指向同一块堆内存空间。
浅拷贝:
package Clone;
import java.io.*;
public class Person implements Cloneable , Serializable {
public String name;
public int page;
public Address address;
public Person(String name, int page) {
this.name = name;
this.page = page;
this.address = new Address();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public int getPage() {
return page;
}
public void setName(String name) {
this.name = name;
}
public void setPage(int page) {
this.page = page;
}
public void setAddress(String provices,String city) {
address.setAddress(provices,city);
}
public void display(String displayname){
System.out.println(displayname+"name"+name+",page"+page+",address"+address);
}
}
package Clone;
import java.io.Serializable;
public class Address implements Serializable {
private String provices;
private String city;
public void setAddress(String provices,String city){
this.provices = provices;
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"provices='" + provices + '\'' +
", city='" + city + '\'' +
'}';
}
}
客户端:
package Clone;
public class shallowClone {
public static void main(String[] args) throws Exception {
Person p1 = new Person("yan",23);
p1.setAddress("山西省","汾阳市");
Person p2 =(Person) p1.clone();
System.out.println("p1"+p1);
System.out.println("p1.getname"+p1.getName().hashCode());
System.out.println("p2"+p2);
System.out.println("p2.getname"+p2.getName().hashCode());
p1.display("p1");
p2.display("p2");
p2.setAddress("北京","北京");
System.out.println("只修改p2");
p1.display("p1");
p2.display("p2");
}
}
调用对象的 clone 方法,必须要让类实现 Cloneable 接口,并且覆写 clone 方法。
但是只修改了p2,却将p1也修改了,也就是说对象 Person 的属性 Address,经过 clone 之后,其实只是复制了其引用,他们指向的还是同一块堆内存空间,当修改其中一个对象的属性 Address,另一个也会跟着变化。
浅拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。
深拷贝:
利用序列化:注意每个需要序列化的类都要实现 Serializable 接口,如果有某个属性不需要序列化,可以将其声明为 transient,即将其排除在克隆属性之外。
//深度拷贝
public Object deepClone() throws Exception{
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
address类改为如下:
package Clone;
import java.io.*;
public class Person implements Cloneable , Serializable {
public String name;
public int page;
public Address address;
public Person(String name, int page) {
this.name = name;
this.page = page;
this.address = new Address();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public int getPage() {
return page;
}
public void setName(String name) {
this.name = name;
}
public void setPage(int page) {
this.page = page;
}
public void setAddress(String provices,String city) {
address.setAddress(provices,city);
}
public void display(String displayname){
System.out.println(displayname+"name"+name+",page"+page+",address"+address);
}
//深度拷贝
public Object deepClone() throws Exception{
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
客户端:
package Clone;
public class Clone {
public static void main(String[] args) throws Exception {
Person p1 = new Person("yan",23);
p1.setAddress("山西省","汾阳市");
Person p2 =(Person) p1.deepClone();
System.out.println("p1"+p1);
System.out.println("p1.getname"+p1.getName().hashCode());
System.out.println("p2"+p2);
System.out.println("p2.getname"+p2.getName().hashCode());
p1.display("p1");
p2.display("p2");
p2.setAddress("北京","北京");
System.out.println("只修改p2");
p1.display("p1");
p2.display("p2");
}
}
原型模式:
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
简历类:
package Prototype;
import java.io.*;
import java.nio.file.Watchable;
public class Resume implements Cloneable, Serializable {
private String name;
private String gender;
private int age;
private workExperience we;
public Resume(){
we = new workExperience();
}
public void display(){
System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public workExperience getWorkExperience(){
return we;
}
public void setWorkExperience(String workDate,String workCompany){
we.setWorkdate(workDate);
we.setWorkCompany(workCompany);
}
public Object deepClone() throws Exception{
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package Prototype;
import java.io.*;
import java.nio.file.Watchable;
public class Resume implements Cloneable, Serializable {
private String name;
private String gender;
private int age;
private workExperience we;
public Resume(){
we = new workExperience();
}
public void display(){
System.out.println(this.getName()+this.getGender()+this.getAge()+this.getWorkExperience().getWorkdate()+this.getWorkExperience().getWorkCompany());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public workExperience getWorkExperience(){
return we;
}
public void setWorkExperience(String workDate,String workCompany){
we.setWorkdate(workDate);
we.setWorkCompany(workCompany);
}
public Object deepClone() throws Exception{
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
工作经历类:
package Prototype;
import java.io.Serializable;
public class workExperience implements Serializable {
private String workdate;
private String workCompany;
public String getWorkdate() {
return workdate;
}
public workExperience setWorkdate(String workdate) {
this.workdate = workdate;
return this;
}
public String getWorkCompany() {
return workCompany;
}
public workExperience setWorkCompany(String workCompany) {
this.workCompany = workCompany;
return this;
}
}
客户端:
package Prototype;
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("浅度拷贝");
Resume r1 = new Resume();
r1.setName("a");
r1.setAge(25);
r1.setGender("男");
r1.setWorkExperience("2000-2009","xx");
r1.display();
Resume r2 = (Resume)r1.clone();
System.out.println("仅修改r2");
r2.setWorkExperience("2000-2009","YY");
r1.display();
r2.display();
System.out.println("深度拷贝");
Resume r3 = (Resume)r1.deepClone();
r3.setWorkExperience("2018-2020","ww");
r1.display();
r3.display();
}
}
浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象;
深拷贝:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象