大话设计模式——8.原型模式(Prototype Pattern)
1.介绍
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。属于创建型模式。
UML图:
1)浅拷贝: 指创建一个新的对象,然后将原始对象的字段值复制到新对象中。如果字段是基本类型,直接复制其值;如果字段是引用类型,则复制其引用,新对象和原对象将共享同一份引用指向相同的内存地址。一般实现Cloneable接口,重写clone()方法。
2)深拷贝: 指创建一个新的对象,然后将原始对象的字段值复制到新对象中。但与浅拷贝不同的是,对于引用类型的字段,深拷贝会递归地复制其所指向的对象,而不是复制引用本身。一般实现Serializable接口进行序列化再反序列化。
2.示例
一个学校的学生信息有着许多可以复用的,因此可以使用原型模式进行设计,快速创建复用的信息。
1)学生对象:Student
public class Student implements Cloneable, Serializable { private String name; private String sex; /** * 年级 */ private String grade; /** * 学校 */ private String schoolName; /** * 学科 */ private List subjects; /** * 浅拷贝 ,调用顶级父类Object的方法 * * @return * @throws CloneNotSupportedException */ @Override protected Student clone() throws CloneNotSupportedException { return (Student) super.clone(); } /** * 深拷贝 * * @return */ public Student deepClone() { try { // 转换二进制输出流,序列化 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(this); // 输入流转换,反序列化,拷贝形成新的对象 ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bai); return (Student) ois.readObject(); } catch (Exception e) { e.printStackTrace(); return null; } } public Student() { } public Student(String name, String sex, String grade, String schoolName, List subjects) { this.name = name; this.sex = sex; this.grade = grade; this.schoolName = schoolName; this.subjects = subjects; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getGrade() { return grade; } public void setGrade(String grade) { this.grade = grade; } public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public List getSubjects() { return subjects; } public void setSubjects(List subjects) { this.subjects = subjects; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", grade='" + grade + '\'' + ", schoolName='" + schoolName + '\'' + ", subjects=" + subjects + '}'; } }
2)运行:
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Student student1 = new Student("大美", "女", "一年级", "大大小学", Arrays.asList("数学", "语文", "英语")); // 浅拷贝 Student student2 = student1.clone(); student2.setName("小美"); student2.getSubjects().set(1,"da"); // 深拷贝 Student student3 = student1.deepClone(); student3.setName("小庄"); student3.setSex("男"); student3.getSubjects().set(1,"hh"); System.out.println(student1); System.out.println(student2); System.out.println(student3); // 浅拷贝,引用类型数据指向共同的地址 System.out.println(student2.getSubjects() == student1.getSubjects()); System.out.println(student3.getSubjects() == student1.getSubjects()); } }
3.总结
1)优点:
a. 当创建新的对象实例较为复杂时,可以简化对象的创建过程,提高新实例的创建效率;
b. 可以辅助实现撤销操作,采取深克隆的方式保存对象的状态,将对象复制⼀份并将其状态保存起来,在需要的时候使其恢复到历史状态。
2)缺点:
a. 每个类都需要重写克隆方法,比较繁琐且不符合开闭原则;
b. 深克隆的实现编写较为复杂,且对象间存在多重嵌套引用时,其中的每个必须支持深克隆。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。