【软件构造】第八章

近期在做实验时遇到需要对程序改造支持原型模式的需求,将其中的经验整理在这里。

原型模式使得程序支持clone,通过clone()而非new的方法生成对象,不能使用简单的super.clone()进行浅拷贝,因为对于引用类型的属性,浅拷贝使得两个引用指向同一个对象,当clone后的对象对这个属性进行修改之后,也使得原对象中的这个属性修改,导致意外的错误。

浅拷贝:对一个对象进行clone生成新的对象,新的对象要开辟一块新的内存来存储,新对象中的基本类型属性和String类型属性都会开辟新的空间存储,但是如果是引用类型的属性,那这个引用类型的属性还是指向原对象的引用属性内存,当对新的对象或原对象的引用属性做出改变的时候,两方的引用属性类型的值同时做出改变。

而Object中的clone方法默认是浅拷贝,所以对于集合类浅拷贝之后,两个对象的内存地址不同,但是集合内对象指向同一地址,所以修改集合对象中的元素时会引发问题,但进行新增或删除就不会影响对方,因为这相当于是对数组做出的改变,clone对象新生成了一个数组。如对于一个 Map<Integer, Set<E>>类型,map在clone之后的clonemap中的set仍指向map中的set,而其中的set是可变类型,所以clonemap的修改会影响到map中的set。

回到程序中,以实现了对circularorbit 的clone()方法为例说明应该何时使用clone的deep clone和shallow clone,首先看circularorbit中的属性如下:

ConcreteCircularorbit属性  

进行浅拷贝之后,因为L中心物体类型、E轨道物体类型以及Track<E>轨道类型都是不可变类,所以无需进行deep clone,在重写的clone方法中,需要对objOnTrack以及fsGraph进行deep clone,如下:

ConcreteCircularorbit中clone方法

其中对于objOnTrack这个map类型的属性,map的value是set<E>,set集合中装的是E轨道物体类型不可变类,但是set是可变的,在clone后的类中对set的一些操作可能影响到原属性,所以需要对set进行clone。而对于fsGraph属性的clone是通过其内部的clone()方法实现的,下面看一下FriendshipGraph的内部是如何实现的clone()方法,首先看其中的属性:

FriendshipGraph属性

其中的属性dismap中的类型是String和Integer,是不可变类型,在clone类修改时,只会将自己的String和Integer指向新的对象,但是不会改变原类disamp中相应的String和Integer指向的对象,所以不需进行额外的deep clone。但是vex中的Vnode是可变的,需要deep clone。

FriendshipGraph中clone方法

对于Vnode的deep clone又是通过在Vnode类中实现的clone()方法。

Vnode中的属性

Vnode中的clone方法

由Vnode中的属性看出clone方法需要实现对Enode的deep clone,对PhysicalObject来说,它是不可变的,所以shallow clone即可。对Enode的deep clone仍是递归的到Enode类中实现clone()方法。

Enode中的属性

Enode中的clone方法

到此,没有新的可变类型引入,已到达clone序列的起点,这样就实现了ConcreteCircularorbit的clone。

而其他的基本类,由于在设计时都是不可变的类,所以内部的属性也都为基本类型,clone()方法直接沿用Object的clone()方法即可,在此不再赘述。

其他类中的clone()方法

总结:

- 浅拷贝 (Shallow Copy):使用一个已知实例的成员变量对新创建实例的成 员变量逐个赋值。

- 深拷贝 (Deep Copy):类的拷贝方法不仅要复制对象的所有非引用成员变量 值(简单数据类型),还要为引用类型(对象)的成员变量创建新的实例,并且 初始化为原对象的值。

- 新对象与原对象要 相互独立,要求deep copy

- 内部的结构,都要 逐层copy,将新对象的reference指向新的内部结构。

- 如果内部只有简单数据类型的变量或 immutable的变量,则直接调用父类缺省的clone函数即可。

 

 有关Hashmap的原对象和clone对象在修改时都发生改变,但进行新增或删除就不会影响对方可见的源码分析:https://blog.csdn.net/m0_37135421/article/details/80522719

posted @ 2019-05-30 00:36  AllenHIT  阅读(125)  评论(0编辑  收藏  举报