设计模式7之原型模式

如果你在开发中遇到需要创建大量的对象,你可以使用传统的构造函数创建对象。但是对于开发来说这样做太麻烦了,有没有高效的生成对象的方式呢?

当然是有的,原型模式就能解决上面的问题。

什么是原型模式

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)

如果已经创建好一个对象,我们可以通过复制的方式来创建一个新的对象。这就是原型模式,使用原型模式创建对象,我们无需知道创建细节。实际这种方式是非常高效的。

我们举个栗子:大家都在Windows上面都安装过JDK吧,我们安装时需要点击很多下一步。这中间可能还要选取安装的路径,选择安装的模块。如果我们在Linux上面安装JDK,只需要将JDK安装文件复制到Linux上,解压即可用。你看在Windows上安装文件比在Linux上安装复杂多了吧。

原型模式的关键在于复制,复制的目的就是为了简化对象创建流程,提高效率。

原型模式的结构

主要包含几个要素:

  • 抽象原型类:定义需要实现的接口

  • 具体原型类:实现抽象原型类的clone()方法

  • 访问类:调用clone()方法复制出来的对象

扫描二维码关注公众号,回复: 12004634 查看本文章

原型模式

要注意,这里的clone()方法是浅拷贝。

结果如下:

关于浅拷贝与深拷贝我查了维基百科,有兴趣的可以去看看原文:

https://en.wikipedia.org/wiki/Object_copying

这里我翻译了:

浅拷贝

复制对象的一种方法是浅层复制。在这种情况下,创建一个新的对象B,将A的字段值复制到B上,这也被称为逐字段复制,字段换字段复制,或字段拷贝,如果字段值是一个对象的引用(如内存地址),它就会复制引用,从而与A引用相同的对象,如果字段值是一个基元类型,它就会复制基元类型的值。在没有基元类型的语言中(在这种语言中,所有的东西都是对象),复制B的所有字段都是引用与原A的字段相同的对象,因此引用的对象是共享的,因此如果其中一个对象被修改(来自A或B),则在另一个对象中可以看到变化。浅层拷贝很简单,通常也很便宜,因为它们通常可以通过简单地精确复制位来实现。

我总结下,浅拷贝中如果原对象里面的属性是基本类型,会将值拷贝到新对象,如果是引用类类型,会使用同一个引用。

深拷贝

另一种方法是深度拷贝,这意味着字段被取消引用:不是对被拷贝对象的引用,而是为任何被引用的对象创建新的拷贝对象,并将对这些对象的引用放在 B 中。结果与浅层拷贝的结果不同,因为拷贝 B 所引用的对象与 A 所引用的对象不同,而且是独立的。由于需要创建额外的对象,深层拷贝的成本较高,而且由于引用可能会形成一个复杂的图形,因此深层拷贝可能会更加复杂。

深度复制是指复制过程递归发生的过程。它意味着首先构造一个新的集合对象,然后用在原始对象中找到的子对象的副本递归地填充它。在深度复制的情况下,对象的副本被复制到其他对象中。这意味着对对象副本的任何更改都不会反映在原始对象中。在 python 中,这个功能是通过 "deepcopy() "函数实现的。

总的来说,深度拷贝就是创建了新的引用。

代码展示

RealizeType

PrototypeTest

测试结果:

具体原型创建成功!
具体原型复制成功!
obj1==obj2?false

原型模式的实现其实很简单,只要调用clone()方法就可以实现属性复制。

关于原型模式的思考

使用原型模式性能优良,在原型模式中,对象不直接new出来,通过在内存中拷贝已有对象,如果你在循环中需要产生大量对象,就可以使用原型模式。

其实有很多地方都使用了原型模式哦。

在Spring中,原型模式应用的非常广泛,例如 scope='prototype'JSON.parseObject() 等都是原型模式的具体应用。

相信你肯定用过BeanUtils.copyProperties作实体拷贝,其实这个拷贝也是浅拷贝。

关于浅拷贝你需要注意的

我们知道,浅拷贝会共用同一个地址,如果一个对象的属性(引用类型)值改变,另一个对象的值也会相应改变。两个对象共享了一个私有变量,你改我改大家都能改,是一种非常不安全的方式,在实际项目中使用还是比较少的(当然, 这也是一种“危机”环境的一种救命方式)

我们用代码来说明一下问题:

浅拷贝问题

我们创建一个用来拷贝的类Citation

测试代码

直接来看看结果:

如果obj2中的Member内容变了,obj1中的Member内容会不会变?

这个问题的答案是会改变

所以在使用clone()拷贝对象时要注意这个问题。

往期推荐

扫码二维码,获取更多精彩。或微信搜Lvshen_9,可后台回复获取资料

1.回复"java" 获取java电子书;

2.回复"python"获取python电子书;

3.回复"算法"获取算法电子书;

4.回复"大数据"获取大数据电子书;

5.回复"spring"获取SpringBoot的学习视频。

6.回复"面试"获取一线大厂面试资料

7.回复"进阶之路"获取Java进阶之路的思维导图

8.回复"手册"获取阿里巴巴Java开发手册(嵩山终极版)

9.回复"总结"获取Java后端面试经验总结PDF版

10.回复"Redis"获取Redis命令手册,和Redis专项面试习题(PDF)

11.回复"并发导图"获取Java并发编程思维导图(xmind终极版)

另:点击【我的福利】有更多惊喜哦。

猜你喜欢

转载自blog.csdn.net/wujialv/article/details/109043823
今日推荐