原型模式(重要):
当需要多次创建相同或相似对象时,可以复制这个对象。
浅克隆:复制对象本身和基本类型的成员变量(String当做引用类型看待),对于引用类型的成员变量仅复制其引用地址,而引用对象不复制。通过覆盖Java中的clone()方法来实现浅克隆,浅克隆的对象须实现Cloneable接口。
深克隆:复制对象全部的内容,对于引用类型的成员变量,由于在堆中复制了其引用对象,所以引用地址肯定发生了变化。在Java中,通过序列化的方式实现深克隆。将原有对象写入流中,写到流中的对象是原有对象的一个拷贝,然后从流中读出来实现深克隆,深克隆的对象须实现Serializable接口。
浅克隆与深克隆的区别是引用类型的成员对象是否复制。
原型模式的适用场景:
1.创建新对象的成本过大,需要多次创建相同或相似对象时
2.系统要保存对象的状态,而对象的状态变化很小,对象占用的内存很小,可以使用原型模式配合备忘录模式来应用。如果对象的状态变化或占用的内存很大,可以采用状态模式。
原型模式的应用:
1.在Struts2中为了保证线程的安全性,Action对象的创建使用了原型模式,当访问一个已经存在Action对象时,通过克隆的方式创建一个新对象,从而保证对象中定义的变量无须进行加锁而实现同步。
原型模式的优点:
1.简化对象的创建过程,提高对象的创建效率
2.由于克隆方法在原型类的内部,因此增加新的原型类不需要修改原有代码
3.可以使用深克隆保存对象的状态
原型模式的缺点:
1.当要克隆已有的类时,需要修改原有代码,违背了开闭原则
2.实现深克隆需要编写较为复杂的代码
原型模式的例子:
要克隆的对象
public class Student implements Cloneable,Serializable{
private String stuName;
private int stuAge;
private School school;
/**
*
* @Description: 浅克隆,需要实现Cloneable接口
* @author doudou
* @date 2019年10月8日
* @return
* @throws
* @return
* @see java.lang.Object#clone()
*/
public Object clone() {
Student student = null;
try {
student = (Student) super.clone();
} catch (Exception e) {
System.out.println("Clone failure");
}
return student;
}
/**
*
* @Description: 深克隆
* @author doudou
* @date 2019年10月8日
* @return
* @throws IOException
* @throws ClassNotFoundException
* @throws
* @return
*/
public Object deepClone() throws IOException, ClassNotFoundException {
//将对象写入流中
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
//将对象从流中取出
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
}
public class School implements Serializable{
}
测试类:
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IOException {
Student student = new Student();
School school = new School();
student.setSchool(school);
student.setStuAge(10);
student.setStuName("doudou");
Student shallowClone = (Student) student.clone();
Student deepClone = (Student) student.deepClone();
System.out.println("student:"+student.toString());
System.out.println("shallowClone:"+(shallowClone.toString()));
System.out.println("shallowClone==student?"+(shallowClone==student));
System.out.println("shallowClone.equals(student)?"+(shallowClone.equals(student)));
System.out.println("shallowClone.getStuName()==student.getStuName()?"+(shallowClone.getStuName()==student.getStuName()));
System.out.println("deepClone:"+(deepClone.toString()));
System.out.println("deepClone==student?"+(deepClone==student));
System.out.println("deepClone.equals(student)?"+(deepClone.equals(student)));
System.out.println("deepClone.getStuName()==student.getStuName()?"+(deepClone.getStuName()==student.getStuName()));
}
}