原型模式
本篇文章是通过看视频学习总结的内容, 如有错误的地方请谅解,并联系博主及时修改,谢谢您的阅读.
何为原型模式?
原型模式可以客观的理解为对象的复制,通过原型模式对原有对象进行复制,对象的复制分为浅克隆和深克隆 。
适用场景:
对象初始化资源比较多new 关键字创建对象过程复杂构造函数逻辑复杂循环过程中创建大量的对象
原型模式的优点:
通过原型模式创建的对象不需要再次走 new 关键字,走构造函数去创建对象,而是直接 copy 内存中的内容,所以性能很高不走构造函数,完美避开了构造函数的约束
原型模式的缺点:
被拷贝的对象中存在对象引用的情况,被引用的对象也需要实现 java.io.Serializable必须实现 java.lang.Cloneable 接口
举个例子:
浅克隆实体类
@Setter
@Getter
@ToString
public class ShallowClone implements Serializable,Cloneable
{
private String username
;
@Override
public Object
clone() {
try {
Object clone
= super.clone();
return clone
;
} catch (Exception ex
) {
return null
;
}
}
}
浅克隆(对象中存在引用,则无法对引用的对象进行拷贝)
public static void main(String
[] args
) {
ShallowClone shallowClone
= new ShallowClone();
shallowClone
.setUsername("张三");
ShallowClone clone
= (ShallowClone
)shallowClone
.clone();
clone
.setUsername("李四");
System
.out
.println(shallowClone
);
System
.out
.println(clone
);
}
浅克隆对象中加入其他对象的引用
@Setter
@Getter
@ToString
public class ShallowClone implements Serializable, Cloneable
{
private String username
;
List
<String> hobbys
;
@Override
public Object
clone() {
try {
Object clone
= super.clone();
return clone
;
} catch (Exception ex
) {
return null
;
}
}
}
浅克隆加入对象引用
public static void main(String
[] args
) {
ShallowClone shallowClone
= new ShallowClone();
shallowClone
.setUsername("张三");
List
<String> hobbys
= new ArrayList<>();
hobbys
.add("唱");
hobbys
.add("跳");
hobbys
.add("rap");
hobbys
.add("篮球");
shallowClone
.setHobbys(hobbys
);
ShallowClone clone
= (ShallowClone
)shallowClone
.clone();
clone
.setUsername("李四");
List
<String> cloneHobbys
= clone
.getHobbys();
cloneHobbys
.add("蔡徐坤");
System
.out
.println(shallowClone
);
System
.out
.println(clone
);
}
通过浅克隆对象中加入对象引用,最终被引用的结果是一样的,可以分析得到实现java.lang.Cloneable 接口只是对对象进行了浅克隆,并非进行对象深克隆,如果被克隆的对象中存在其他对象的引用的时候,那么被克隆出来的值和原来的值是一致的,且内存地址也是相同的,那么被克隆的引用是直接复制了对象的地址,而不是对象中的内容。深克隆
@Setter
@Getter
@ToString
public class DeepEntity implements Cloneable, Serializable
{
private String userName
;
private String password
;
private List
<String> phone
;
public DeepEntity serializationDeepClone
(){
try {
ByteArrayOutputStream bos
= new ByteArrayOutputStream();
ObjectOutputStream oos
= new ObjectOutputStream(bos
);
oos
.writeObject(this);
ByteArrayInputStream bis
= new ByteArrayInputStream(bos
.toByteArray());
ObjectInputStream ois
= new ObjectInputStream(bis
);
return (DeepEntity
)ois
.readObject();
}catch (Exception ex
) {
ex
.printStackTrace();
}
return null
;
}
public DeepEntity JsonDeepClone
(){
String json
= JSON
.toJSONString(this);
return JSON
.parseObject(json
, DeepEntity
.class);
}
public DeepEntity
beanUtilDeepClone() {
DeepEntity deepEntity
= new DeepEntity();
BeanUtil
.copyProperties(this, deepEntity
, true);
return deepEntity
;
}
}
测试三种深克隆方法
package com
.example
.learn
.design
.patterns
.prototype
;
import com
.example
.learn
.design
.patterns
.prototype
.deep
.DeepEntity
;
import com
.example
.learn
.design
.patterns
.prototype
.shallow
.Entity
;
import com
.example
.learn
.design
.patterns
.prototype
.shallow
.ShallowClone
;
import java
.util
.ArrayList
;
import java
.util
.List
;
public class PrototypeClient {
public static void main(String
[] args
) {
deepClone
();
}
public static void deepClone
(){
DeepEntity entity
= new DeepEntity();
entity
.setPassword("123456");
entity
.setUserName("zyred");
List
<String> hobbys
= new ArrayList<>();
hobbys
.add("唱");
hobbys
.add("跳");
hobbys
.add("rap");
hobbys
.add("篮球");
entity
.setHobbys(hobbys
);
DeepEntity clone
= entity
.serializationDeepClone();
clone
.getHobbys().add("蔡徐坤");
System
.out
.println("entity: " + entity
);
System
.out
.println("clone: " + clone
);
System
.out
.println(entity
.getHobbys() == clone
.getHobbys());
}
}
总结:
浅克隆是无法克隆对象中被引用的对象,只会复制引用的地址深克隆是对整个对象中的内容无死角的复制,而不是复制引用的地址,在工作中建议适用深拷贝。