原型设计模式
-
简单介绍
原型设计模式是一种创建型设计模式。通过原型实例对象创建与该实例相同类型的对象实例,且将原型(可以简单理解为成员属性)拷贝给新创建的对象实例。
-
使用场景
需要创建与某个实例对象具有相同状态(成员变量值相同)的对象。
-
场景举例
Spring获取Bean对象时,其中一种方式采用了原型设计模式。通过配置scope属性为prototype来指定创建原型对象。
-
UML类图
-
拷贝方式
-
浅拷贝
对于基本数据类型的成员变量,浅拷贝直接进行值传递,而对于引用数据类型的成员变量,浅拷贝则只进行引用的传递
-
深拷贝
对于基本数据类型的成员变量,深拷贝直接进行值传递,而对于引用数据类型的成员变量,深拷贝为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直至该对象可达的所有对象。
-
-
具体实现
模拟简历的拷贝,其中简历类(Resume)所依赖引用数据类型为头像类(Photo)
-
浅拷贝
/** * 头像照片类,被简历类(Resume)所依赖的应用数据类型 */ public class Photo { private Integer height; private Integer Width; // get和set方法省略 }
/** * 简历类,通过重写Object中的clone()方法来实现 */ public class Resume implements Cloneable { private String name; private Integer age; private Double weight; /** * 引用数据类型,用来表示简历上的头像照片 */ private Photo photo; /** * 通过调用父类Object中的clone()方法完成简历对象的浅拷贝 */ @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // get和set方法省略 }
-
深拷贝(方式一:重写引用数据类型的clone()方法)
/** * 头像照片类,被简历类(Resume)所依赖的应用数据类型 */ public class Photo implements Cloneable { private Integer height; private Integer Width; /** * 重写clone()方法 */ @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } // get和set方法省略 }
/** * 简历类,通过重写Object中的clone()方法来实现 */ public class Resume implements Cloneable { private String name; private Integer age; private Double weight; /** * 引用数据类型,用来表示简历上的头像照片 */ private Photo photo; /** * 通过调用父类Object中的clone()方法完成简历对象的浅拷贝 */ @Override protected Object clone() throws CloneNotSupportedException { Resume resumeClone = (Resume) super.clone(); // 对Resume实例对象中的引用数据类型进行拷贝对象的复制,从而达到深拷贝 resumeClone.setPhoto((Photo) resumeClone.getPhoto().clone()); return resumeClone; } // get和set方法省略 }
-
深拷贝(序列化)
/** * 头像照片类,被简历类(Resume)所依赖的应用数据类型 */ public class Photo implements Serializable { private Integer height; private Integer Width; // get和set方法省略 }
/** * 简历类,通过序列化的方法来完成深拷贝(推荐) */ public class Resume implements Serializable { private String name; private Integer age; private Double weight; private Photo photo; public Object deepCopy() throws Exception { // 序列化 ByteArrayOutputStream bos; ObjectOutputStream oos; bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(this); // 反序列化 ByteArrayInputStream bis; ObjectInputStream ois; bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); // 关流操作省略 return ois.readObject(); } }
-
-
源码展示
-
JDK中的实现了Cloneable接口的类,都采用了原型设计模式来获取实例对象,如常用的容器类ArrayList等
public class ArrayList<E> implements Cloneable { public Object clone() { try { // 重写类clone()方法,实现了深拷贝,容器元素都是独立的 ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } } }
-