大话设计模式——8.原型模式(Prototype Pattern)

03-23 1079阅读

1.介绍

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。属于创建型模式。

UML图:

大话设计模式——8.原型模式(Prototype Pattern)

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. 深克隆的实现编写较为复杂,且对象间存在多重嵌套引用时,其中的每个必须支持深克隆。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]