一、原型模式概述
原型模式是指:用原型实例指定创建对象的种类,并通过拷贝这些原型,创建新的对象。原型模式是一种创建型设计模式,允许一个对象再创建一个可定制的对象,无须知道知道如何创建的对象。用大白话解释就是,已知一个对象,再根据这个对象复制一个一模一样的对象。
二、关于深拷贝和浅拷贝
深拷贝:就是对象里面无论有属性或者方法,在复制新对象的时候,都全部拷贝过来,形成一个新的对象。
浅拷贝:就是只能复制对象里面的基本属性,如果对象里面有些属性是另一个对象,则不是复制一个新的,而是将拷贝的对象里面的这个对象和被复制的这个对象里面的对象属性是同一个对象。这么说估计估计有点晕,一图解千言,看图:
浅拷贝就是对象里面的对象不能复制,这里在克隆的时候,只是将A对象中的school对象的引用传递给了B对象的school。那么就意味,无论你是改变A对象里面的school还是改变B对象里面的school,都将相互影响。那么深拷贝就不言而喻了三,就是school也完全复制了一个新的,A对象和B对象里面的school互相没有关系了。
三、实现浅拷贝
就是刚才的Sudent类,要实现克隆,必须要实现Cloneable接口,如下:
public class Student implements Cloneable{
private String username;
private String password;
private School school;
public Student(String username, String password, School school) {
this.username = username;
this.password = password;
this.school = school;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
/**
* 实现克隆方法
* @return
*/
@Override
protected Object clone() {
Student student = null;
try {
student = (Student) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
}
public class School {
private String name;
private String address;
public School(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
开始克隆:
四、clone方法实现深拷贝
clone方法实现深拷贝,也简单再将school对象也克隆一次,当然Student也要实现Cloneable接口
public class School implements Cloneable {
private String name;
private String address;
public School(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
protected Object clone() {
School school = null;
try {
school = (School) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return school;
}
}
public class Student implements Cloneable{
private String username;
private String password;
private School school;
public Student(String username, String password, School school) {
this.username = username;
this.password = password;
this.school = school;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
/**
* 实现克隆方法
* @return
*/
@Override
protected Object clone() {
Student student = null;
try {
student = (Student) super.clone();
student.school = (School) school.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
}
请注意Student的clone方法不一样了,在student的clone方法中,又实现了调用了一次school的clone方法。
开始克隆:
相信大家都发现了一个问题了,那就是如果对象中有对象,对象中还有对象,那么就会无休止的去写clone方法。所以下面用对象序列化实现深拷贝。
五、对象序列化实现深拷贝
依然是创建Student类和School类,但是要想实现序列化和反序列化,两个类都必须实现Serializable接口
import java.io.Serializable;
public class School implements Serializable {
private String name;
private String address;
public School(String name, String address) {
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
import java.io.*;
public class Student implements Serializable {
private String username;
private String password;
private School school;
public Student deepClone() {
//输出流
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);
return (Student)objectInputStream.readObject();
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Student(String username, String password, School school) {
this.username = username;
this.password = password;
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", school=" + school +
'}';
}
}
客户端代码如下:
public class Client {
public static void main(String[] args) {
Student student = new Student("波仔","123",new School("杠山大学","中岗"));
Student newStudent = student.deepClone();
System.out.println(newStudent);
System.out.println(student == newStudent);
}
}