当前位置: 首页 > news >正文

设计模式—创建型模式之原型模式

设计模式—创建型模式之原型模式

原型模式(Prototype Pattern)用于创建重复的对象,同时又能保证性能。

本体给外部提供一个克隆体进行使用。

比如我们做一个SjdwzMybatis,用来操作数据库,从数据库里面查出很多记录,其中很多记录改变很少。每次查数据库,把所有数据都封装一个对象,然后返回。假设有很多线程,来查如下记录:

Student student = new Student("张三","男")

如果每次都创建对象封装并返回,这样系统就会有很多student;这样就会浪费内存。

Student类如下:

public class Student {private String name;private Integer age;public Student() {System.out.println("创建了Student对象");}//省略getter() 、 setter() toString()
}

SjdwzMybatis如下:

public class SjdwzMybatis {/*** 通过name获取Student*/public Student queryStudent(String name){return queryStudentFromDB(name);}/*** 演示从数据库查Student*/private Student queryStudentFromDB(String name) {//简单演示,查询到了System.out.println("从数据库查询到了:"+name);Student student = new Student();student.setName(name);student.setAge(16);return student;}
}

测试类:

public class ProtoTypeTest {public static void main(String[] args) {SjdwzMybatis sjdwzMybatis = new SjdwzMybatis();Student stu1 = sjdwzMybatis.queryStudent("zhangsan");Student stu2 = sjdwzMybatis.queryStudent("zhangsan");Student stu3 = sjdwzMybatis.queryStudent("zhangsan");Student stu4 = sjdwzMybatis.queryStudent("zhangsan");}
}

这样会有大量具有相同属性的student被外部创建,同时查库次数过多。

我们是否能设计一个缓存,来保存查过的内容,再查相同的记录时,可以很快拿到原来的原型对象呢?

那我们的SjdwzMybatis便变成了如下代码:

public class SjdwzMybatis {//缓存private Map<String,Student> stuCache = new HashMap<>();/*** 通过name获取Student*/public Student queryStudent(String name){if(stuCache.containsKey(name)){return stuCache.get(name);}else{return queryStudentFromDB(name);}}/*** 演示从数据库查Student*/private Student queryStudentFromDB(String name) {//简单演示,查询到了System.out.println("从数据库查询到了:"+name);Student student = new Student();student.setName(name);student.setAge(16);//存入内存stuCache.put(name,student);return student;}
}

但是这是否会有问题呢?

修改属性

如果我们把stu1的属性改了,那么stu2、stu3、stu4的属性也会被改变,这会影响到我们缓存里的数据,造成脏缓存数据;同时我们查出来的内容,并没有提交修改,不能就把原数据给修改掉。

原型模式

我们把Student修改成如下代码,这便是原型模式:

//实现Cloneable接口,这只是一个标记,还需要重写clone()方法
public class Student implements Cloneable{private String name;private Integer age;//重写clone方法@Overrideprotected Object clone() throws CloneNotSupportedException {Student student = new Student();student.setName(this.name);student.setAge(this.age);return student;}
}

然后SjdwzMybatis修改为如下代码:

public class SjdwzMybatis {//缓存private Map<String,Student> stuCache = new HashMap<>();/*** 通过name获取Student*/public Student queryStudent(String name) throws CloneNotSupportedException {if(stuCache.containsKey(name)){return (Student) stuCache.get(name).clone();}else{return queryStudentFromDB(name);}}/*** 演示从数据库查Student*/private Student queryStudentFromDB(String name) throws CloneNotSupportedException {//简单演示,查询到了System.out.println("从数据库查询到了:"+name);Student student = new Student();student.setName(name);student.setAge(16);//存入内存stuCache.put(name,(Student) student.clone());return student;}
}

从数据库查出来放入缓存的对象与从缓存取出来的都是clone出来的。

可以看到,我们对stu1修改,并不会影响其他的数据了。

效果

http://www.lryc.cn/news/216929.html

相关文章:

  • Zygote进程通信为什么用Socket而不是Binder?
  • API接口加密,解决自动化中登录问题
  • COCOS2DX3.17.2 Android升级targetSDK30问题解决方案
  • HarmonyOS鸿蒙原生应用开发设计- 隐私声明
  • 【面试精选】00后卷王带你三天刷完软件测试面试八股文
  • k-means算法c++实现
  • oracle查询哪些用户下有表
  • 机器人连杆惯量参数辨识(估计)
  • 一座 “数智桥梁”,华为助力“天堑变通途”
  • C#知识总结 基础篇(上)
  • 照片编辑软件Affinity Photo 2 for Mac v2.1.1中文激活版 2024年最新中文版下载
  • TPAMI 2023 | Temporal Perceiver:通用时序边界检测方法
  • Unity-UV展开工具
  • springboot actuator jvm监控丢失
  • UDP服务端和客户端通信代码开发流程
  • 数据库实验:SQL的数据定义与单表查询
  • P3398 仓鼠找 sugar
  • C# 发送邮件
  • Zeal下载文档慢的问题
  • HR模块开发(1):简单的开发流程和注意事项
  • 创建Vue实例
  • 2024上海国际人工智能展(CSITF)以“技术,让生活更精彩”为核心理念,以“创新驱动发展,保护知识产权,促进技术贸易”为主题
  • Vue3使用Monaco-editor
  • java 根据ip获取到城市 GeoLite2-City.mmdb
  • kaggle使用说明
  • BUUCTF FLAG 1
  • 万物皆可“云” 从杭州云栖大会看数智生活的未来
  • LeetCode1518 换水问题
  • 强大日志查看器,助力数据联动分析
  • HIBS一些简介