UML类图
代码示例
实际应用中,原型模式可以简单理解为克隆操作。在大多数面向对象编程语言中,实现克隆操作并不复杂,对于Java,我们只需继承Cloneable接口,并重写Object的clone()即可(非必须)。
public class Teacher implements Cloneable {
/**
* 姓名
*/
private String name;
private Teacher(String name) {
try {
// 模拟初始化资源耗时较多
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher("李老师");
// output: teacher = Teacher{name='李老师'}
System.out.println("teacher = " + teacher);
// clone is much faster
Teacher cloneTeacher = (Teacher) teacher.clone();
// output: cloneTeacher = Teacher{name='李老师'}
System.out.println("cloneTeacher = " + cloneTeacher);
}
}
clone()方法会抛出未检查的CloneNotSupportedException,通过源码了解下什么情况下会产生该异常。
该方法有native
修饰,这说明它的具体实现在底层(参考JNI)。文档说明,在当前克隆类没有实现Cloneable接口的情况下,该异常将会触发。另外,还有这么一句值得我们留意,Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.
,这说明clone()实现的是浅拷贝而不是深拷贝(下个话题深入)。最后,重写clone()是非必须的,一般重写只是用来提高方法的访问权限。
总结思考
原型模式通过(浅)拷贝现有对象以生成新的对象,属于创建型模式中的一种。对比通过new的方式来实例化对象,这种模式不用重新初始化对象,可以动态的获得对象运行时的状态,也适用于需要优化性能的场景,例如当类的初始化需要消耗非常多的资源,就可以考虑使用这种模式了。
接触原型模式,不可避免的就是关于浅拷贝和深拷贝的问题,下一篇准备深入了解下这个话题。