前言
在我们工作中经常能遇到大幅度使用get或set方法,例如下面这样的代码
public Student copy(Student oldStudent){
Student newStudent = new Student();
newStudent.setAge(oldStudent.getAge());
newStudent.setName(oldStudent.getName());
return newStudent;
}
当Student的属性少还可以介绍,如果当Student的属性过于多,那么这样的代码属于"纯体力劳动",原型模式就可以帮我们解决这样的问题。
我们看看Cloneable接口
public interface Cloneable {
}
克隆模式是配合Cloneable接口一起使用的,我们会发现Cloneable是一个空的接口,Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的Clone方法,然后通过类调用clone方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException(克隆不被支持)异常。Object中clone方法:
protected native Object clone() throws CloneNotSupportedException;
native关键字
被native修饰都是调用底层的方法(不是java编写的,例如:调用是在JVM编写的C的接口),每一个native方法在jvm中都有一个同名的实现体,native方法在逻辑上的判断都是由实现体实现的,另外这种native修饰的方法对返回类型,异常控制等都没有约束。 由此可见,这里判断是否实现cloneable接口,是在调用jvm中的实现体时进行判断的。
原型模式适用的场景
- 类初始化消耗资源过多
- 使用new生成一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造方法比较复杂
- 在循环体中产生大量对象
原型模式的应用
- 在Spring中,原型模式应用得十分广泛,例如scope=“prototype”
- 我们经常使用的JSON.parseObject()也是使用原型模式
原型模式实战
浅克隆
- 编写Student类重写Cloneable
package pers.design.pattern.原型模式.浅克隆;
public class Student implements Cloneable {
private int age;
private String name;
public Student(){
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}