赞
踩
原型模式是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1 如果创建行的对象成本比较大,可以通过复制的方式减少创建的成本。
2 一个类的信息很多,但是又需要一个新的类,新的类和以前的类不同的地方很少,此时可以使用原型模式进行复制操作得到新的对象,再对新对象改变一些信息即可。
3 其他
在Object类中提供了clone()方法,当简单的重写该方法时,由于该方法是protected的,所以只能是同包下的类才能访问,修饰符可以改成public的,让所有类可以进行克隆操作。
protected native Object clone() throws CloneNotSupportedException;
如果只重写了clone()方法,此时别的类在调用clone()方法,会在运行时出现运行时异常CloneNotSupportedException,
克隆类还需要再实现Cloneable接口,这是一个标识接口,实现了这个接口的类JVM才会知道类是支持克隆操作的。
public interface Cloneable {}
浅克隆的情况
要进行克隆的类实现Cloneable接口,重写Object类继承来的clone()方法
- /**
- * 房子类
- */
- public class House implements Cloneable {
-
- // 住房编号
- String roomId;
-
- // 住房面积
- int area;
-
- // 房子价值
- double price;
-
- // 房主
- Person owner;
-
- public House() {
-
- }
-
- public House(String roomId, int area, double price, Person owner) {
- this.roomId = roomId;
- this.area = area;
- this.price = price;
- this.owner = owner;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
-
-
-
- /**
- * 房主类
- */
- public class Person implements Cloneable {
-
- // 身份证号
- int id;
-
- // 姓名
- String name;
-
- public Person() {
- }
-
- public Person(int id, String name) {
- this.id = id;
- this.name = name;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
- }
-
-
-
- /**
- * 只支持浅克隆
- */
- public class Client {
-
- public static void main(String[] args) throws CloneNotSupportedException {
-
- Person MrLiu = new Person(1, "Mr.Liu");
-
- House h1 = new House("1302", 78, 2900, MrLiu);
- House h2 = (House) h1.clone();
-
- System.out.println(h1.owner == h2.owner);
- }
- }
h1和h2不是同一个对象,但是h1的owner和h2的owner是同一个对象,表明是浅复制(浅克隆,即对象里的引用对象只拷贝引用,而不拷贝引用指向的对象,基本类型会拷贝)。
自定义clone过程实现深克隆
将上面的House类的clone()重写成自己实现克隆
- /**
- * 嵌套的使用克隆,如果类的对象属性很多,都需要手动编码实现,这个让我很难受。
- * @return
- */
- @Override
- protected House clone() {
- House house = null;
- try {
- // 先以浅复制的形式复制house,
- // 此时house里的owner属性复制的引用而没有复制对象
- house = (House) super.clone();
- // 再以浅复制的形式复制owner
- house.owner = (Person) house.owner.clone();
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- return house;
- }
Debug后可以看出,h1和h2不是同一个对象,h1的owner和h2的owner也不是同一个对象,是深克隆。
序列化实现深克隆
此处只给出如何实现验证这个克隆方案,具体如何实现序列化见其他优秀博客,写的很详细。
Serializable也是一个标识接口,表明实现该接口的类可以进行序列化。
public interface Serializable { }
这里要注意的是House类实现了序列化,House类里的引用类型也要实现序列化,要不然还是会出现序列化错误。
House类实现序列化,而Person类没有实现序列化接口,运行时报NotSerializableException异常。
- /**
- * 房子类
- */
- public class House implements Serializable {
- // 住房编号
- String roomId;
- // 住房面积
- int area;
- // 房子价值
- double price;
- // 房主
- Person owner;
-
- public House() {
- }
-
- public House(String roomId, int area, double price, Person owner) {
- this.roomId = roomId;
- this.area = area;
- this.price = price;
- this.owner = owner;
- }
- }
-
-
- /**
- * 房主类
- */
- public class Person implements Serializable {
-
- // 身份证号
- int id;
- // 姓名
- String name;
-
- public Person() {
- }
-
- public Person(int id, String name) {
- this.id = id;
- this.name = name;
- }
- }
-
-
- /**
- * 序列化的方式实现深克隆
- */
- public class Client {
-
- public static void main(String[] args) throws IOException, ClassNotFoundException {
- Person MrLiu = new Person(1, "Mr.Liu");
-
- House h1 = new House("1302", 78, 2900, MrLiu);
-
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\test\\aaa")));
- oos.writeObject(h1);
- oos.close();
-
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\test\\aaa")));
-
- House h2 = (House) ois.readObject();
- System.out.println(h2);
- ois.close();
- }
-
- }
Debug后可以看出,h1和h2不是同一个对象,h1的owner和h2的owner也不是同一个对象,实现了深克隆。
参考第2条,什么时候要用
能力有限,未能深入到这步,请体谅。
能力有限,未能深入到这步,请体谅。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。