大战设计模式(第二季)【3】———— 从源码看原型模式
前言
对于原型模式比较简单,其实可能我们听到的比较少,但是在实际中其实用到的地方你没有注意。
原型模式基础点:https://www.cnblogs.com/linkstar/p/7810951.html
原型模式用一句话说就是,通过拷贝来创建复杂对象来减少资源开销。
在循环体中产生大量对象的时候比较常用。
需要注意的是原型模式的浅拷贝和深拷贝。
从ArrayList看原型模式
首先我们可以看到ArrayList实现了Cloneable接口
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable

然后看到重现了clone方法,内部实现的时候注意一个点,使用Arrays.copyOf方法进行数组的拷贝,因为ArrayList内部是数组实现的,并且注意这里重现将modCount赋值为0了。
因为Arrays.copyOf是浅拷贝,所以数组里面的对象还是引用的原地址,这就是一个坑了,我们在使用原型模式的时候,如果有类似ArrayList这样的对象一定要注意。
spring中的原型模式
spring的bean默认是单例模式的,也可以声明为Prototype原型模式,这样每次获取这个对象的时候都会通过原型创建一个新的实例。
在AbstractBeanFactory中有一个doGetBean这个方法,这个方法很长里面记录了bean的创建。有兴趣的朋友请把它看完。
我们这边注意到里面的这一段:

这一段很容易理解,如果这个bean的定义是单例的,那么就直接通过createBean这个方法去创建这个对象就可以了。
如果这个对象声明的是原型模式,那么就会先创建一个原型实例prototypeInstance然后通过这个原型实例创建bean
从MyBatis看原型模式
// CacheKey.java
@Override
public CacheKey clone() throws CloneNotSupportedException {
CacheKey clonedCacheKey = (CacheKey) super.clone();
clonedCacheKey.updateList = new ArrayList<>(updateList);
return clonedCacheKey;
}
对于缓存CacheKey的clone方法来看,我们可以看到在使用clone创建新的对象的时候,对于内部的updateList需要重新new出来,进行深拷贝。创建出来的对象的使用不能对原对象产生影响,这里一定要注意。
总结
作为原型模式其实比较简单,坑点主要存在于浅拷贝和深拷贝,在创建复杂对象的时候,合理运用一个原型去拷贝生成对象比直接创建来的效率高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
2018-02-26 在SpringBoot中配置aop
2017-02-26 阿里巴巴Java开发手册———总结
2017-02-26 阿里巴巴Java开发手册———个人追加的见解和补充(五)