原型模式

原型模式

原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
优点:当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
实现:原型模式的核心是重写Object类中clone方法,通过该方法进行对象的拷贝,Java中提供了一个Cloneable接口来标示该对象是可拷贝的,它的作用是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法,如果没有实现Cloneable接口,在运行时会抛出CloneNotSupportedException异常。
uml图:
原型模式_第1张图片
原型模式分为深拷贝和浅拷贝。
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。
在浅拷贝中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。简单来说,在浅拷贝中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。

/**
 * @author chen
 */
public class StudentPrototype implements Cloneable {
    String name="";
    String schoolName="";
    TeacherPrototype teacherPrototype;
    @Override
    public StudentPrototype clone(){
        StudentPrototype prototype = null;
        try {
            prototype = (StudentPrototype)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    public String getName() {
        return name;
    }

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

    public TeacherPrototype getTeacherPrototype() {
        return teacherPrototype;
    }

    public void setTeacherPrototype(TeacherPrototype teacherPrototype) {
        this.teacherPrototype = teacherPrototype;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
}

public class TeacherPrototype {
    String name="";
    @Override
    public TeacherPrototype clone(){
        TeacherPrototype prototype = null;
        try {
            prototype = (TeacherPrototype)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class StudentTest {
    public static void main(String[] args) {
        StudentPrototype studentPrototype1=new StudentPrototype();
        TeacherPrototype teacherPrototype=new TeacherPrototype();
        studentPrototype1.setName("张三");
        studentPrototype1.setSchoolName("四中");
        teacherPrototype.setName("张三的老师");
        studentPrototype1.setTeacherPrototype(teacherPrototype);
        StudentPrototype studentPrototype2=studentPrototype1.clone();
        studentPrototype2.setName("李四");
        studentPrototype2.getTeacherPrototype().setName("李四的老师");
        System.out.println("学校:"+studentPrototype1.getSchoolName()+",,,学生:"+studentPrototype1.getName()+",,,老师:"+studentPrototype1.getTeacherPrototype().getName());
        System.out.println("学校:"+studentPrototype2.getSchoolName()+",,,学生:"+studentPrototype2.getName()+",,,老师:"+studentPrototype2.getTeacherPrototype().getName());

    }
}

输出:

学校:四中,,,学生:张三,,,老师:李四的老师
学校:四中,,,学生:李四,,,老师:李四的老师

我们在给学生“李四”修改老师时,学生“张三”的老师也被修改了。

在深拷贝中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深拷贝将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深拷贝中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

/**
 * @author chen
 */
public class StudentPrototype implements Cloneable {
   private String name="";
   private String schoolName="";
   private TeacherPrototype teacherPrototype;
    @Override
    public StudentPrototype clone(){
        StudentPrototype prototype = null;
        try {
            prototype = (StudentPrototype)super.clone();
            TeacherPrototype teacherPrototype=this.teacherPrototype.clone();
            prototype.setTeacherPrototype(teacherPrototype);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    public String getName() {
        return name;
    }

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

    public TeacherPrototype getTeacherPrototype() {
        return teacherPrototype;
    }

    public void setTeacherPrototype(TeacherPrototype teacherPrototype) {
        this.teacherPrototype = teacherPrototype;
    }

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
}
public class TeacherPrototype implements Cloneable{
   private String name="";
    @Override
    public TeacherPrototype clone(){
        TeacherPrototype prototype = null;
        try {
            prototype = (TeacherPrototype)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class StudentTest {
    public static void main(String[] args) {
        StudentPrototype studentPrototype1=new StudentPrototype();
        TeacherPrototype teacherPrototype=new TeacherPrototype();
        studentPrototype1.setName("张三");
        studentPrototype1.setSchoolName("四中");
        teacherPrototype.setName("张三的老师");
        studentPrototype1.setTeacherPrototype(teacherPrototype);
        StudentPrototype studentPrototype2=studentPrototype1.clone();
        studentPrototype2.setName("李四");
        studentPrototype2.getTeacherPrototype().setName("李四的老师");
        System.out.println("学校:"+studentPrototype1.getSchoolName()+",,,学生:"+studentPrototype1.getName()+",,,老师:"+studentPrototype1.getTeacherPrototype().getName());
        System.out.println("学校:"+studentPrototype2.getSchoolName()+",,,学生:"+studentPrototype2.getName()+",,,老师:"+studentPrototype2.getTeacherPrototype().getName());

    }
}

输出:

学校:四中,,,学生:张三,,,老师:张三的老师
学校:四中,,,学生:李四,,,老师:李四的老师

这样对学生李四的老师赋值时不会改变学生李三老师的值。

你可能感兴趣的:(原型模式)