通俗易懂的java设计模式之原型模式

66 阅读3分钟

我们在写简历的时候往往会找一个现成的模板,这要比自己设计个模板要快很多。在程序上也是一样,我们第一次new了一个对象,后续有新的需求我们要复用这个对象,难道还要频繁的new吗?这个对象小还好说,要是这个对象比较大创建过程时间长,显然通过new的方式性能就很低了。这个时候就需要考虑到Copy这个对象啦,以这个对象为模板。而Copy这个对象的方式就是原型模式。 说起原型模式首先不得不提到一个词,拷贝。它又分为深拷贝和浅拷贝。那二者有啥区别呢,别急,先看代码案例你就知道了。

原型模式之浅拷贝

代码如下:

public class Prototype {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        //浅拷贝和深拷贝
        Citation citation = new Citation();//创建原型对象
        Student student = new Student();
        student.setName("张三");
        citation.setStudent(student);
        Citation clone = citation.clone();//拷贝原型对象
        clone.getStudent().setName("李四");
        citation.show();
        clone.show();
    }
}
class Citation implements Cloneable,Serializable{
    private Student student;
    public void setStudent(Student student) { this.student = student;}
    public Student getStudent() {return student;}
    public void show(){System.out.println(student.getName()+"同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状");}
    //浅拷贝
    protected Citation clone() throws CloneNotSupportedException {
        return (Citation)super.clone();
    }
}
class Student implements Serializable,Cloneable {
    private String name;
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

运行结果如下:

李四同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状
李四同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状

原型模式之深拷贝

代码如下:

public class Prototype {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        //浅拷贝和深拷贝
        Citation citation = new Citation();//创建原型对象
        Student student = new Student();
        student.setName("张三");
        citation.setStudent(student);
        Citation clone = citation.clone();//拷贝原型对象
        clone.getStudent().setName("李四");
        citation.show();
        clone.show();
    }
}
class Citation implements Cloneable,Serializable{
    private Student student;
    public void setStudent(Student student) { this.student = student;}
    public Student getStudent() {return student;}
    public void show(){System.out.println(student.getName()+"同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状");}
    //深拷贝
    public Citation clone() throws CloneNotSupportedException {
        Citation deepClone = (Citation)super.clone();
        deepClone.student = (Student) student.clone();
        return deepClone;
    }
}
class Student implements Serializable,Cloneable {
    private String name;
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

运行结果如下:

张三同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状
李四同学,在2023学年第一学期中表现优异,被评为三好学生,特颁此状

在浅拷贝案例中可以看到我们把Clone的对象中学生的名字换成李四后,原有的对象学生的名字也换成了李四。而在深拷贝中我们虽然把Clone的对象中学生的名字换成李四,原有对象学生的名字仍然没有改变为李四,还是原有的张三。可见浅拷贝中复制后的对象所有变量都含有与原来对象相同的值,而且所有对其他对象的引用都指向了原来的对象。而深拷贝中被复制对象的引用指向了新的对象,而不是原有的被引用的对象。

可能你就要问了,在享元模式中,我也可以直接获取对象,为什么还需要原型模式?

其实享元模式与原型模式非常相似,它们都是为了解决重复创建对象的性能优化方案,它们主要区别如下:

  1. 原型模式是在直接创建对象的代价比克隆更大时通过克隆来解决重复创建的问题;享元模式是在对创建过多的性质相似的对象时通过缓存来解决重复创建的问题。
  2. 原型模式创建的对象属性完全一样,而享元模式会根据不同的外部状态创建不一样的对象实例。