设计模式——原型模式
传统模式创建大量对象
代码实现
public class Citation {
private String name;
@Override
public String toString() {
return "Citation{" +
"name='" + name + '\'' +
'}';
}
}
创建5个对象
public class Client {
public static void main(String[] args) {
Citation citation = new Citation();
Citation citation1 = new Citation();
Citation citation2 = new Citation();
Citation citation3 = new Citation();
Citation citation4 = new Citation();
}
}
传统方式的优缺点
解决思路:
原型模式
1.1 基本介绍
一句话解释就是:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。
1.2 原型模式创建
Java中的Object类中提供了 clone() 方法来实现浅克隆。 Cloneable 接口是上面的类图中的抽
象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。代码如下:
public class Citation implements Cloneable{
private String name;
public Citation(String name) {
this.name = name;
System.out.println(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Citation{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Citation clone() throws CloneNotSupportedException {
return (Citation) super.clone();
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation("三好学生");
Citation clone = citation.clone();
}
}
1.3 深拷贝和浅拷贝
1.3.1 浅拷贝
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原
有属性所指向的对象的内存地址。
代码示例:
public class Citation implements Cloneable{
private String name;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Citation() {
}
public Citation(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
public String toString() {
return "Citation{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student {
private String address;
private String name;
@Override
public String toString() {
return "Student{" +
"address='" + address + '\'' +
", name='" + name + '\'' +
'}';
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation();
citation.setName("三好学生");
Student student = new Student();
student.setName("张三");
citation.setStudent(student);
Citation clone = (Citation) citation.clone();
clone.setName("五好学生");
Student student1 = clone.getStudent();
student1.setName("李四");
citation.show();
clone.show();
System.out.println(student == student1);
System.out.println(citation.getStudent());
System.out.println(clone.getStudent());
}
}
最后输出的结果
三好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
五好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
true
Student{address='null', name='李四'}
Student{address='null', name='李四'}
说明
stu对象和stu1对象是同一个对象,就会产生将stu1对象中name属性值改为“李四”,两个
Citation(奖状)对象中显示的都是李四。这就是浅克隆的效果,对具体原型类(Citation)中的
引用类型的属性进行引用的复制。
1.3.1 深拷贝
代码示例:
重写 clone 方法来实现深拷贝
student类实现clone方法,citation类型重写clone方法实现,对引用类型的数据进行处理:
public class Citation implements Cloneable{
private String name;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Citation() {
}
public Citation(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
public String toString() {
return "Citation{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Citation citation = (Citation) super.clone();
// 对引用类型 进行clone方法处理
citation.student = (Student) citation.getStudent().clone();
return citation;
}
}
得到的结果是:
三好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
五好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
false
Student{address='null', name='张三'}
Student{address='null', name='李四'}
通过对象序列化实现深拷贝:
类记得实现Serializable接口,不然会报错的,并且属性里面有对象属性也需要实现。
public class Citation implements Cloneable, Serializable {
private String name;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Citation() {
}
public Citation(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!");
}
@Override
public String toString() {
return "Citation{" +
"name='" + name + '\'' +
'}';
}
public Object deepClone(){
ByteArrayInputStream bis = null;
ByteArrayOutputStream bos = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try{
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return ois.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
Citation citation = (Citation) super.clone();
// 对引用类型 进行clone方法处理
// citation.student = (Student) citation.getStudent().clone();
return citation;
}
}
public class Student implements Cloneable, Serializable {
private String address;
private String name;
@Override
public String toString() {
return "Student{" +
"address='" + address + '\'' +
", name='" + name + '\'' +
'}';
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// @Override
// protected Object clone() throws CloneNotSupportedException {
// return super.clone();
// }
}
注意,这里调用的是deepClone方法
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation();
citation.setName("三好学生");
Student student = new Student();
student.setName("张三");
citation.setStudent(student);
Citation clone = (Citation) citation.deepClone();
clone.setName("五好学生");
Student student1 = clone.getStudent();
student1.setName("李四");
citation.show();
clone.show();
System.out.println(student == student1);
System.out.println(citation.getStudent());
System.out.println(clone.getStudent());
}
}
结果输出:
三好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
五好学生同学:在2020学年第一学期中表现优秀,被评为三好学生。特发此状!
false
Student{address='null', name='张三'}
Student{address='null', name='李四'}
序列化拷贝的核心代码:
public Object deepClone(){
ByteArrayInputStream bis = null;
ByteArrayOutputStream bos = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try{
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return ois.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}