设计模式5.原型模式
Posted jiazhongxin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式5.原型模式相关的知识,希望对你有一定的参考价值。
原型模式
原型模式(Prototype Pattern),使用原型实例复制生成新的对象。若某个类的实例化比较复杂,完全重新创建成本较大,这时可以使用原型模式。这种模式是在内存(堆)中拷贝对象,比直接new一个对象节省资源。对象拷贝的时候构造器是不会执行。
结构图:
Prototype:提供拷贝方法的原型接口
ConcretePrototype:实现拷贝自身方法的类
Java中提供了实现原型模式的方式:
·实现Cloneable接口;
·重写clone方法(默认的protected改为public)
这里Cloneable即可为Prototype。
1. 浅拷贝
只拷贝对象内的基本数据类型,数组和对象仅拷贝其引用,没有真实拷贝一个新的数组/对象。
例:
public class Pen { private String name; private float cost; public Pen(String name, float cost) { this.name = name; this.cost = cost; } }
public class Student implements Cloneable{ // ConcretePrototype private String name; private int age; private Pen pen; public Student(String name, int age, Pen pen) { this.name = name; this.age = age; this.pen = pen; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } // setter/getter省略 }
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student student1 = new Student("jzx",18,new Pen("真彩",3.5f)); Student student2 = (Student)student1.clone(); System.out.println("student1的hashCode:"+ student1.hashCode()); System.out.println("student2的hashCode:"+ student2.hashCode()); System.out.println("student1的pen的hashCode:"+ student1.getPen().hashCode()); System.out.println("student2的pen的hashCode:"+ student2.getPen().hashCode()); } }
输出:
student1的hashCode:1735600054 student2的hashCode:21685669 student1的pen的hashCode:2133927002 student2的pen的hashCode:2133927002
从hashCode可以看出,副本student2中的实例对象pen和student1的实例对象是同一个。
2.深拷贝
全部拷贝,真正的完全拷贝。
方式一:
让被拷贝对象中的实例对象的类也实现Cloneable接口,并重写clone方法,同时被拷贝对象的类中重写clone时对实例对象额外拷贝。
例:
public class Pen implements Cloneable{ private String name; private float cost; public Pen(String name, float cost) { this.name = name; this.cost = cost; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
public class Student implements Cloneable{ private String name; private int age; private Pen pen; public Student(String name, int age,Pen pen) { this.name = name; this.age = age; this.pen = pen; } @Override public Object clone() throws CloneNotSupportedException { Student student = (Student)super.clone(); student.pen = (Pen)this.pen.clone(); return student; } // setter/getter 省略 }
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student student1 = new Student("jzx",18,new Pen("真彩",3.5f)); Student student2 = (Student)student1.clone(); System.out.println("student1的hashCode:"+ student1.hashCode()); System.out.println("student2的hashCode:"+ student2.hashCode()); System.out.println("student1的pen的hashCode:"+ student1.getPen().hashCode()); System.out.println("student2的pen的hashCode:"+ student2.getPen().hashCode()); } }
输出:
student1的hashCode:1735600054 student2的hashCode:21685669 student1的Pen的hashCode:2133927002 student2的Pen的hashCode:1836019240
这时,从hashCode可以看出,副本student2中的实例对象pen和student1的实例对象pen不再是同一个了,是完完全全的拷贝。
方式二:
被拷贝对象及其中的实例对象都实现序列化,重写clone方法时进行序列化和反序列化。
例:
public class Pen implements Serializable { private String name; private float cost; public Pen(String name, float cost) { this.name = name; this.cost = cost; } }
public class Student implements Cloneable,Serializable{ private String name; private int age; private Pen pen; public Student(String name, int age,Pen pen) { this.name = name; this.age = age; this.pen = pen; } @Override public Object clone() throws CloneNotSupportedException { // 序列化 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(bos); } catch (IOException e) { e.printStackTrace(); } try { oos.writeObject(this); } catch (IOException e) { e.printStackTrace(); } // 反序列化 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = null; try { ois = new ObjectInputStream(bis); } catch (IOException e) { e.printStackTrace(); } Student student = null; try { student = (Student) ois.readObject(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return student; } // setter/getter省略 }
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Student student1 = new Student("jzx",18,new Pen("真彩",3.5f)); Student student2 = (Student)student1.clone(); System.out.println("student1的hashCode:"+ student1.hashCode()); System.out.println("student2的hashCode:"+ student2.hashCode()); System.out.println("student1的pen的hashCode:"+ student1.getPen().hashCode()); System.out.println("student2的pen的hashCode:"+ student2.getPen().hashCode()); } }
输出:
student1的hashCode:621009875 student2的hashCode:1072408673 student1的pen的hashCode:1554874502 student2的pen的hashCode:1531448569
可见,序列化实现了深拷贝。
以上是关于设计模式5.原型模式的主要内容,如果未能解决你的问题,请参考以下文章