代码改变世界

23种设计模式中的原型模式

2017-08-09 16:02  猪牙哥  阅读(182)  评论(0编辑  收藏  举报

原型模式:通过复制现有实例来创建新的实例,无须知道相应类的信息。

个人见解:在大量循环时,需要初始化对象,用 原型模式能节省大量的初始化所花费的时间,值得一谈的是浅复制和深复制

浅复制:Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝

代码

在这里我定义了一个学生类Student.java

public class Student implements Cloneable {
    private String name;

    public Student(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

还有一个Teacher.java

public class Teacher implements Cloneable {
    private String name;
    private Student[] students;

    public Teacher(String name, Student... students) {
        super();
        this.name = name;
        this.students = students;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student[] getStudents() {
        return students;
    }

    public void setStudents(Student[] students) {
        this.students = students;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

然后测试

public static void main(String[] args) throws CloneNotSupportedException {
        Teacher t=new Teacher("李老师", new Student("小明"),new Student("小红"));
        System.out.println(t);
        System.out.println(t.getStudents());
        System.out.println(Arrays.toString(t.getStudents()));
        System.out.println("-------------------------------------------------");
        Teacher teacher = (Teacher) t.clone();
        System.out.println(teacher);
        System.out.println(teacher.getStudents());
        System.out.println(Arrays.toString(teacher.getStudents()));
    }

输出结果

可以看到拷贝出来的对象跟被拷贝的对象内存地址不一样,也就是不同的对象,但是指向的Student数组的内存地址是一样的,那就是说改变拷贝出来的对象中的Student数组会影响被拷贝的对象中的Student数组,这个在开发中很明显不是我们想要的,那么我们看一下深复制。

深复制:要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝

实例代码,

只需要改动Teacher.java

public class Teacher implements Cloneable {
    private String name;
    private Student[] students;

    public Teacher(String name, Student... students) {
        super();
        this.name = name;
        this.students = students;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student[] getStudents() {
        return students;
    }

    public void setStudents(Student[] students) {
        this.students = students;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Teacher clone = null;
        clone = (Teacher) super.clone();
        clone.students = this.students.clone();
        return clone;
    }
}

输出结果

很明显,指向Student数组都不一样,那么就是连Student数组也拷贝了

大家有没有发现,为什么Student数组里面的字符串地址都是一样?这实际上是Java虚拟机对字符串的一种优化,并不在本章节的讨论范围内,大家有兴趣可以去了解下。