![设计模式就该这样学:基于经典框架源码和真实业务场景](https://wfqqreader-1252317822.image.myqcloud.com/cover/758/33114758/b_33114758.jpg)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
9.3 原型模式在框架源码中的应用
9.3.1 原型模式在JDK源码中的应用
首先定义JDK中的Cloneable接口。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_19.jpg?sign=1739700070-YOdx4u1agOhMljesaGzJkbwvHSzKrXAh-0-2a9d65bcafd37a11485d8cafc1a2d412)
定义接口还是很简单的,我们找源码其实只需要看哪些接口实现了Cloneable即可。来看ArrayList类的实现。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_20.jpg?sign=1739700070-hUYbhVgogwHH3dRmMvQOcWr8pLnfWBUv-0-5c3e8b62c1dd769284d37098aff1963e)
我们发现,clone()方法只是将List中的元素循环遍历了一遍。此时,再思考一下,是不是这种形式就是深克隆呢?其实用代码验证一下就知道了,继续修改ConcretePrototype类,增加一个deepCloneHobbies()方法。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_21.jpg?sign=1739700070-Lvk8Ppiajz4BI4qU4HY7zcaqPJUQAVsi-0-5bc4770bf4eb0284e0caa365d3ae277a)
客户端代码修改如下。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_22.jpg?sign=1739700070-lZVba2UJRwUmAdAiOcSslwRaERsXVCBH-0-28d98b1b05c9103ac308d4addeec339c)
运行代码也能得到期望的结果。但是这样的代码其实是硬编码。如果在对象中声明了各种集合类型,则每种情况都需要单独处理。因此,深克隆的写法一般会直接用序列化来操作。
9.3.2 原型模式在Spring源码中的应用
在Spring中,如果用户将创建对象的方式设置为原型,则每次调用getBean()的时候都要重新创建一个新的对象返回。和单例模式一样,还是继续来看doGetBean()方法的代码片段。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_23.jpg?sign=1739700070-8jzecKBPsfSx9oiwnKVkJ5ZKXuDtb5lD-0-ce7a4cf856b4aa2f9d7f2651be24fe4f)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt011_24.jpg?sign=1739700070-EFrraBWWCAKGiNPdVHCZI4hgniC7m3yj-0-0b6037d2f83d507b11bad651ae799e3a)
Spring中创建对象的方式默认采用单例模式,可以通过设置@Scope(“prototype”)注解将其改为原型模式。但是,采用单例模式创建或者采用原型模式创建,只能二选一。