1、原型模式概述
原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。——百度百科
2、原型模式实现方式(浅克隆和深克隆)
1、Work类
package com.parttern.prototype;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
@Getter
@Setter
@ToString
public class Work implements Serializable, Cloneable {
String name;
String location;
@Override
protected Work clone() throws CloneNotSupportedException {
return (Work)super.clone();
}
}
2、Person类(原型类)
package com.parttern.prototype;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@ToString
public class Person implements Cloneable, Serializable{
private String name;
private int age;
private Work work;
private List<String> hobbyList;
/**
* 1、浅克隆,仅拷贝基础类型及String,无法拷贝对象中的对象
*/
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
/**
* 2、深克隆1,其实是对对象中的每个对象进行浅拷贝,代码量较多且不易于维护
* 此外,像List这种无法重写实现Cloneable接口的类无法实现直接克隆,除非new对象手工实现
*/
public Person deepClone1() {
try {
Work work1 = this.work.clone();
Person person = (Person)super.clone();
person.setWork(work1);
/* List<String> hobbyList1 = new ArrayList<>(this.getHobbyList());
person.setHobbyList(hobbyList1);*/
return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return new Person();
}
/**
* 3、深克隆2,采用序列化反序列化的形式克隆对象,一劳永逸
*/
public Person deepClone2() {
Person person = null;
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person"));) {
oos.writeObject(this);
person = (Person)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return person;
}
}
3、测试类PrototypeDemo
package com.parttern.prototype;
import java.util.ArrayList;
import java.util.List;
public class PrototypeDemo {
public static void main(String[] args) {
System.out.println("SimpleClone:");
simpleClone();
System.out.println("DeepClone1:");
deepClone1();
System.out.println("DeepClone2:");
deepClone2();
}
private static void simpleClone(){
Person person1 = initPerson();
Person person2 = null;
try {
person2 = modPerson(person1.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
printPerson(person1, person2);
}
private static void deepClone1(){
Person person1 = initPerson();
Person person2 = modPerson(person1.deepClone1());
printPerson(person1, person2);
}
private static void deepClone2(){
Person person1 = initPerson();
Person person2 = modPerson(person1.deepClone2());
printPerson(person1, person2);
}
private static Person initPerson(){
Person person = new Person();
person.setName("zhangsan");
person.setAge(20);
Work work = new Work();
work.setName("ICBC");
work.setLocation("Hangzhou");
person.setWork(work);
List<String> hobbyList = new ArrayList<>();
hobbyList.add("basketball");
hobbyList.add("violin");
person.setHobbyList(hobbyList);
return person;
}
private static Person modPerson(Person person){
person.setAge(30);
person.setName("lisilisi");
person.getWork().setName("Bestpay");
person.getWork().setLocation("Shanghai");
person.getHobbyList().add("reading");
return person;
}
private static void printPerson(Person person1, Person person2){
System.out.println(person1);
System.out.println(person2);
}
}
4、输出结果:
SimpleClone:
Person(name=zhangsan, age=20, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
DeepClone1:
Person(name=zhangsan, age=20, work=Work(name=ICBC, location=Hangzhou), hobbyList=[basketball, violin, reading])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
DeepClone2:
Person(name=zhangsan, age=20, work=Work(name=ICBC, location=Hangzhou), hobbyList=[basketball, violin])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
总结:
1、SimpleClone只能简单复制基本属性和String,对于引用属性实际上还是指向同一个对象。所以work和hobbyList都相等。
2、DeepClone1通过对引用类重写clone来实现,这种方式有两种问题,一是如果该类增加一个对象,就需要增加对应的clone逻辑,代码复杂;二是对于List这种无法实现Cloneable接口的类无法重写,只能通过new对象然后addAll来实现,违背原型模式的初衷。所以Work不相等但是hobbyList还是相等。
3、通过序列化反序列化来生成一个新的对象,两个对象及引用的对象内存地址完全不同。所以hobbyList也不相等。