设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123425 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

47 | 原型模式:如何最快速地clone一个HashMap散列表?

耗时和耗内存空间
节省创建时间
使用深度拷贝创建新对象
使用浅拷贝创建新对象
序列化和反序列化
递归拷贝对象
浅拷贝
深拷贝
解决方法分享
修改不可变对象的容器
不可变对象和可变对象的处理
添加、更新和删除关键词的处理
原型模式的优缺点
浅拷贝的实现方法
深拷贝的实现方法
原型模式的两种实现方法
原型模式的应用场景
什么是原型模式?
课堂讨论
应用场景讨论
原型模式

该思维导图由 AI 生成,仅供参考

对于创建型模式,前面我们已经讲了单例模式、工厂模式、建造者模式,今天我们来讲最后一个:原型模式。
对于熟悉 JavaScript 语言的前端程序员来说,原型模式是一种比较常用的开发模式。这是因为,有别于 Java、C++ 等基于类的面向对象编程语言,JavaScript 是一种基于原型的面向对象编程语言。即便 JavaScript 现在也引入了类的概念,但它也只是基于原型的语法糖而已。不过,如果你熟悉的是 Java、C++ 等这些编程语言,那在实际的开发中,就很少用到原型模式了。
今天的讲解跟具体某一语言的语法机制无关,而是通过一个 clone 散列表的例子带你搞清楚:原型模式的应用场景,以及它的两种实现方式:深拷贝和浅拷贝。虽然原型模式的原理和代码实现非常简单,但今天举的例子还是稍微有点复杂的,你要跟上我的思路,多动脑思考一下。
话不多说,让我们正式开始今天的学习吧!

原型模式的原理与应用

如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了原型模式的应用场景和两种实现方式:深拷贝和浅拷贝。通过一个HashMap散列表的例子,生动阐述了对象创建成本较高且差异不大时,利用原型模式可以节省创建时间的优势。文章重点讲解了深拷贝和浅拷贝的区别,以及在实际应用中需要注意对象的引用关系。此外,还提出了两种深拷贝的实现方法,并探讨了在特定应用场景下如何选择合适的拷贝方式。总的来说,本文内容丰富,对于开发人员快速了解原型模式具有一定的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(91)

  • 最新
  • 精选
  • 冬瓜蔡
    日常开发中常用的是spring提供的对象之间拷贝的方法: BeanUtils.copyProperties 1、如果是基础类型,则没有问题。 2、如果要拷贝对象里面有小对象,且小对象的全限定名不一样,则拷贝结束后,该对象为null; public class Person { private Photo photo; } 3、如果要拷贝对象里面有集合,集合里面存放的是小对象,则会由于泛型的存在,可以拷贝成功,但是这个拷贝的对象是错误的,会在后续使用过程中产生问题 public class Person { private List<Photo> photo; } 本质上BeanUtils.copyProperties是浅拷贝,在使用过程中需要对嵌套对象或者集合进行额外处理

    作者回复: ������

    2020-11-17
    3
    4
  • 南北少卿
    如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同) ... 这句话没有想明白

    作者回复: 你联系一下上下文看下,都有讲到的

    2020-07-05
  • 唯她命
    public class Demo { private ConcurrentHashMap<String, SearchWord> currentKeywords = new ConcurrentHashMap<>(); private long lastUpdateTime = -1; public void refresh() { // 从数据库中取出更新时间>lastUpdateTime的数据,放入到currentKeywords中 List<SearchWord> toBeUpdatedSearchWords = getSearchWords(lastUpdateTime); long maxNewUpdatedTime = lastUpdateTime; for (SearchWord searchWord : toBeUpdatedSearchWords) { if (searchWord.getLastUpdateTime() > maxNewUpdatedTime) { maxNewUpdatedTime = searchWord.getLastUpdateTime(); } } 代码有问题啊, List<SearchWord> toBeUpdatedSearchWords = getSearchWords(lastUpdateTime); toBeUpdatedSearchWords里的数据是改过的数据,时间都大于lastUpdateTime 那为啥下面还要searchWord.getLastUpdateTime() > maxNewUpdatedTime????

    作者回复: lastUpdateTime maxNewUpdatedTime searchWord.getLastUpdateTime()三者的关系你理一理

    2020-07-05
    2
  • L🚲🐱
    问题 1: 逻辑删除即可 问题 2: 返回深拷贝对象
    2020-02-19
    2
    94
  • skull
    原型模式,最为常用经典就是BeanUtils
    2020-04-24
    59
  • 辣么大
    问题1: 方法一:新旧的数据取交集,可以删除旧map中的删除关键字,之后的逻辑就和文章中一样了。 方法二:逻辑删除,当map的size中已删除占比过高时,resize map。 争哥说:这里我们利用了 Java 中的 clone() 语法来复制一个对象。如果你熟悉的语言没有这个语法,那把数据从 currentKeywords 中一个个取出来,然后再重新计算哈希值,放入到 newKeywords 中也是可以接受的。 Java HashMap的clone方法就把数据取出来,计算hash值,在放回去的。clone方法中,调用了putMapEntries方法,其中有一关键的一行,克隆重新计算了hash值: putVal(hash(key), key, value, false, evict); 文章中的深复制:为什么SearchWord不重写clone方法呢? @Override protected Object clone() throws CloneNotSupportedException { SearchWord newWord = new SearchWord(this.keyWord, this.times, this.tmstamp); return newWord; }
    2020-02-19
    2
    18
  • 岁月
    课堂讨论题 关键字如果支持删除, 最简单高效的方法就是在数据表里加一个delete bool类型的字段, 占用空间不多, 但是很方便程序识别最近更新的数据里面, 有哪条是需要删除的. 不过这样会带来一个问题, 就是插入新关键字的时候, 要先检查一下是否存在同名的关键字, 有的话要把delete字段修改为false, 所以还需要对关键字建立索引, 这样可以高效查找出是否存在同名关键字
    2020-02-21
    3
    17
  • 新的起点,新的开始^_^
    我有个问题,最后一种方式使用copy()的浅拷贝+对象替换可以提高效率。但是copy()之后,数据库中更没有发生变化的数据其实newKeywords中指向的还是之前的对象引用啊,不是一个新的对象,那这个结果不久和需求冲突了吗?需求是:任何时刻,系统 A 中的所有数据都必须是同一个版本的。举个例子,比如说我修改了一个newKeywords中value对应的SearchWord对象的某个属性,那么响应的,currentKeywords中肯定也会发生变化,因为SearchWord地址值时一样的,这个就不是刚开始讲的深拷贝得到的是一份完完全全独立的对象,它不是独立的,只有数据库中被更新过的数据是独立的,因为执行了map.remove()和map.put()
    2020-04-26
    8
    15
  • 安静
    老师,就是java分层架构中各层的对象,比如VO,BO,PO之间的互相转换,使用的就是原型模式,而做业务开发每天都要与这些打交道。
    2020-04-08
    1
    14
  • 不似旧日
    既然说在Java中不常用那我就不看了,以后有时间再学。
    2020-02-24
    2
    13
收起评论
显示
设置
留言
91
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部