原型模式
Posted hhhshct
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原型模式相关的知识,希望对你有一定的参考价值。
原型模式定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
在JAVA语言中使用原型模式是非常简单的,这是因为Object类当中提供了一个本地方法clone,而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝。
从原型模式的使用方式不难推断出,原型模式常使用于以下场景:
1、对象的创建非常复杂,可以使用原型模式快捷的创建对象。
2、在运行过程中不知道对象的具体类型,可使用原型模式创建一个相同类型的对象,或者在运行过程中动态的获取到一个对象的状态。
由于clone方法是由虚拟机直接复制内存块执行,所以在速度上比使用new的方式创建对象要快,并且在拷贝对象时不会执行对应类的构造方法。
提到原型模式,就不得不提浅拷贝和深拷贝。浅拷贝是指将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。深拷贝将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制。
下面我们来看一个浅拷贝的例子
package prototype; public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { super(); this.name = name; this.age = age; } }
package prototype; public class Family implements Cloneable{ private String address; private Student student; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public Family clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (Family) obj; } }
编写测试代码,结果如下:
可以看到我们copy得来的对象fa2中持有的Student实例和fa中的是一个,所以当我们对fa2中student对象进行修改时,会影响到原来的fa,那么如何实现深拷贝呢?有两种方式。
1、要实现深度拷贝,则需要将实现了Cloneable接口并重写了clone方法的类中,所有的引用类型也全部实现Cloneable接口并重写clone方法,而且需要将引用类型的属性全部拷贝一遍。
修改Student和Fimaly类如下
package prototype; public class Student implements Cloneable{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student clone() { Object obj = null; try { obj = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (Student) obj; } }
package prototype; public class Family implements Cloneable{ private String address; private Student student; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } public Family clone() { Object obj = null; try { obj = super.clone(); ((Family)obj).setStudent(this.student.clone()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (Family) obj; } }
执行测试代码如下:
2、利用序列化,我们的目标类要实现Serializable接口
修改Student和Fimaly类如下
package prototype; import java.io.Serializable; public class Student implements Serializable{ private static final long serialVersionUID = -3865833738045253326L; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { super(); this.name = name; this.age = age; } }
package prototype; import java.io.Serializable; public class Family implements Serializable{ private static final long serialVersionUID = 7498435126824884787L; private String address; private Student student; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } }
测试类
package prototype; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class Client2 { public static Family depCopy(Family fa) { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); try { ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(fa); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream inStream = new ObjectInputStream(byteIn); Family fa2 = (Family) inStream.readObject(); return fa2; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { Student stu = new Student("张三", 12); Family fa = new Family(); fa.setAddress("北京"); fa.setStudent(stu); Family fa2 = depCopy(fa); System.out.println(fa2.getStudent() == fa.getStudent()); } }
结果自然是false,就不再贴出了。
以上是关于原型模式的主要内容,如果未能解决你的问题,请参考以下文章