一、定义
复制运行时的对象,克隆出一个一模一样的对象;
hashcode和引用地址不同,只有内容相同。
原型模式:
- 浅克隆:创建一个新对象,新对象的地址指向原来的引用
- 深克隆:重新创建一个对象,不再指向原有的对象地址
基于二进制流,比new快
二、实现
实现Cloneable接口
对象克隆:
public class PrototypeImpl implements Cloneable {
private ArrayList list = new ArrayList();
@Override
public PrototypeImpl clone() {
PrototypeImpl prototype = null;
try {
// 对象克隆
prototype = (PrototypeImpl)super.clone();
// 克隆集合
// 数组,容器,集合,对象引用需要另行克隆
prototype.list = (ArrayList)this.list.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
public class CreatePrototype extends PrototypeImpl {
public void show(){
System.out.println("原型模式的实现类......");
}
}
public class TestDemo {
public static void main(String[] args) throws CloneNotSupportedException {
CreatePrototype prototype = new CreatePrototype();
// 克隆出一个新的对象
CreatePrototype prototype1= (CreatePrototype)prototype.clone();
prototype1.show();
}
}
三、深度克隆
public class Person implements Cloneable{
private String name;
private Child child;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
@Override
protected Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", child=" + child +
'}';
}
public Person(String name) {
this.name = name;
}
}
public class Child implements Cloneable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Child(String name) {
this.name = name;
}
@Override
protected Child clone() {
try {
return (Child) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "Child{" +
"name='" + name + '\'' +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("父亲");
person.setChild(new Child("孩子"));
//Person{name='父亲', child=Child{name='孩子'}}
System.out.println(person);
Person clonePerson = person.clone();
//Person{name='父亲', child=Child{name='孩子'}}
System.out.println(clonePerson);
//false
System.out.println(person==clonePerson);
}
}
浅克隆:
存在的问题:复制的是引用地址,会导致克隆对象的修改影响了原有对象。
public class Test {
public static void main(String[] args) {
Person person = new Person("父亲");
person.setChild(new Child("孩子"));
//person:Person{name='父亲', child=Child{name='孩子'}}
System.out.println("person:"+person);
Person clonePerson = person.clone();
clonePerson.getChild().setName("孩子2");
//clonePerson:Person{name='父亲', child=Child{name='孩子2'}}
System.out.println("clonePerson:"+clonePerson);
//person:Person{name='父亲', child=Child{name='孩子2'}}
System.out.println("person:"+person);
}
}
1.重写clone方法,依次调用成员变量的clone方法
@Override
protected Person clone() {
try {
Person person = (Person) super.clone();
Child child = person.getChild().clone();
person.setChild(child);
return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public class Test {
public static void main(String[] args) {
Person person = new Person("父亲");
person.setChild(new Child("孩子"));
//person:Person{name='父亲', child=Child{name='孩子'}}
System.out.println("person:"+person);
Person clonePerson = person.clone();
clonePerson.getChild().setName("孩子2");
//clonePerson:Person{name='父亲', child=Child{name='孩子2'}}
System.out.println("clonePerson:"+clonePerson);
//person:Person{name='父亲', child=Child{name='孩子'}}
System.out.println("person:"+person);
}
}
2.通过序列化和反序列化实现
类实现序列化
public class Person implements Cloneable,Serializable
public class Child implements Cloneable, Serializable
@Override
protected Person clone() {
ByteArrayOutputStream byteArrayOutputStream =null;
ObjectOutputStream objectOutputStream =null;
ByteArrayInputStream byteArrayInputStream =null;
ObjectInputStream objectInputStream =null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
objectInputStream = new ObjectInputStream(byteArrayInputStream);
Person person = (Person)objectInputStream.readObject();
return person;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
byteArrayOutputStream.close();
byteArrayInputStream.close();
objectOutputStream.close();
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
3.使用工具类来实现序列化和反序列化
- BeanUtils
- MapStruct
网友评论