原型模式(Prototype)
- 用于创建重复的对象,同时又能保证性能。
- 本体给外部提供一个克隆体进行使用

原型模式的代码实现
- Student类,实现Cloneable接口,表明该类允许被克隆
@Data
public class Student implements Cloneable{
private String name;
private Integer age;
private ClassInfo classInfo;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public Object clone() throws CloneNotSupportedException {
Student student = new Student();
student.setName(name);
student.setAge(age);
student.setClassInfo(classInfo);
return student;
}
}
- 模拟从数据库中查询数据,然后克隆该数据,以防止某个用户修改对其他用户可见
public class SchoolMybatis {
private Map<String,Student> studentCache = new HashMap<>();
public Student getStudent(String studentName) throws Exception {
Student student = null;
if(!studentCache.containsKey(studentName)){
student = getStudentFromDb(studentName);
}else {
student = studentCache.get(studentName);
System.out.println("从缓存中拿到的是:"+student);
student = (Student) student.clone();
}
return student;
}
private Student getStudentFromDb(String studentName) throws Exception{
System.out.println("从数据库查到:"+studentName);
Student student = new Student();
student.setName(studentName);
student.setAge(18);
ClassInfo classInfo = new ClassInfo(1,"数学");
student.setClassInfo(classInfo);
studentCache.put(student.getName(), (Student) student.clone());
return student;
}
}
Student zhangsan = mybatis.getStudent("zhangsan");
System.out.println("1==>"+zhangsan);
zhangsan.setName("lisi");
System.out.println("zhangsan自己改了:"+zhangsan);
Student zhangsan2 = mybatis.getStudent("zhangsan");
System.out.println("2-->"+zhangsan2);
Student zhangsan3 = mybatis.getStudent("zhangsan");
System.out.println("3-->"+zhangsan3);
Student zhangsan4 = mybatis.getStudent("zhangsan");
System.out.println("4-->"+zhangsan4);
System.out.println(zhangsan == zhangsan3);
从数据库查到:zhangsan
1==>Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
zhangsan自己改了:Student(name=lisi, age=18, classInfo=ClassInfo(className=数学, id=1))
从缓存中拿到的是:Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
2-->Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
从缓存中拿到的是:Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
3-->Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
从缓存中拿到的是:Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
4-->Student(name=zhangsan, age=18, classInfo=ClassInfo(className=数学, id=1))
什么场景下使用原型模式
- 资源优化
- 性能和安全要求
- 一个对象多个修改者的场景
- 一个多项需要提供给其他对象访问,而且各个调用者都需要对其值修改,此种情况下,可以考虑使用原型模式拷贝多个对象供调用者进行使用。