Java设计模式之原型模式
原型模式属于创建型模式,原型模式用于直接创建一个对象代价比较大时使用,通过拷贝原型创建新的对象。一般情况,原型模式和工厂模式一起出现,很少单独出现。
一、原型模式的两种实现
(1):实现Cloneable,重写clone()方法(浅拷贝)
(2):实现Serializable ,读取二进制流(深拷贝)
二、原型模式浅拷贝UML类图
三、原型模式深拷贝UML类图
浅拷贝和深拷贝的基本介绍
浅拷贝:
- 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递。 基本类型的拷贝,其中一个对象修改了该值,不会影响另外一个。
- 对于数据类型是引用类型的成员变量,浅拷贝会进行引用传递。浅拷贝会把内存地址赋值给成员变量,他们指向同一个内存空间,改变其中的一个值,会影响另一个。
深拷贝:
- 对于数据类型是基本数据类型的成员变量时,深拷贝也会直接进行值传递,基本类型的拷贝,其中一个对象修改了该值,不会影响另外一个。
- 对于数据类型是引用类型的成员变量,深拷贝会拷贝整个对象,指向不同内存空间,改变其中一个,不会对另一个产生影响。
- 对于多层对象拷贝,需要实现Cloneable 并重写 clone() 方法,实现对象的层层拷贝。
第一种: 实现Cloneable,重写clone()方法
/**
* @author yly
* @ClassName Sheep
* @Date 2020/2/19 14:10
* @Version 1.0
**/
public class Sheep implements Cloneable{
private String name;
private String type;
private String color;
public Sheep(String name, String type, String color) {
this.name = name;
this.type = type;
this.color = color;
}
@Override
public Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
}catch (Exception e){
System.out.println(e.getMessage());
}
return sheep;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return type;
}
public void setAge(String age) {
this.type = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
使用sheep调用clone()方法实现浅拷贝
/**
* @author yly
* @ClassName Demo
* @Date 2020/2/19 14:14
* @Version 1.0
**/
public class Demo {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", "山羊", "白色");
Sheep sheep1 = (Sheep) sheep.clone();//克隆
Sheep sheep2 = (Sheep) sheep.clone();//克隆
System.out.println(sheep.getName()+"--"+sheep.getType()+"--"+sheep.getColor());
System.out.println(sheep1.getName()+"--"+sheep1.getType()+"--"+sheep1.getColor());
System.out.println(sheep2.getName()+"--"+sheep2.getType()+"--"+sheep2.getColor());
}
}
第二种: 实现Serializable ,读取二进制流
/**
* @author yly
* @ClassName Sheep2
* @Date 2020/2/19 23:00
* @Version 1.0
**/
public class DeepCopy implements Serializable,Cloneable {
private String name;
private String type;
private String color;
public DeepCopy(String name, String type, String color) {
this.name = name;
this.type = type;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
实现深拷贝
/**
* @author yly
* @ClassName DeepProtoType
* @Date 2020/2/19 23:03
* @Version 1.0
**/
public class DeepProtoType implements Serializable,Cloneable {
public String name;
public DeepCopy deepCopy;
public DeepProtoType() {
}
//第一种 深拷贝方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
deep = super.clone();
DeepProtoType deepProtoType = (DeepProtoType)deep;
deepProtoType.deepCopy = (DeepCopy) deepCopy.clone();
return deepProtoType;
}
//深拷第二种
public Object deepClone(){
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepProtoType copyObj = (DeepProtoType)ois.readObject();
return copyObj;
} catch (IOException | ClassNotFoundException e) {
return null;
}finally {
try {
bos.close();
oos.close();
bis.close();
ois.close();
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}
创建Demo调用两种深拷贝方法
/**
* @author yly
* @ClassName Client
* @Date 2020/2/19 23:14
* @Version 1.0
**/
public class Demo{
public static void main(String[] args) throws CloneNotSupportedException {
DeepProtoType deepProtoType = new DeepProtoType();
deepProtoType.name = "deepType";
deepProtoType.deepCopy = new DeepCopy("小花","岩羊","棕色");
//方式1 深拷贝
DeepProtoType deep = (DeepProtoType)deepProtoType.clone();
System.out.println(deepProtoType.deepCopy.getName()+"---"+deepProtoType.deepCopy.hashCode());
System.out.println(deep.deepCopy.getName()+"---"+deep.deepCopy.hashCode());
System.out.println();
//方式二 深拷贝
DeepProtoType deep2 = (DeepProtoType)deepProtoType.deepClone();
System.out.println(deepProtoType.deepCopy.getName()+"---"+deepProtoType.deepCopy.hashCode());
System.out.println(deep2.deepCopy.getName()+"---"+deep2.deepCopy.hashCode());
}
}
原型模式的优点:简化对象创建过程,提高效率。如果原始对象发生变化,其他克隆对象也会发生相应的变化,无需修改代码
原型模式的缺点:需要每个类实现克隆的方法,对于新创建的类不难,但是对于已经存在的类进行改造时有时会很复杂。需要修改源代码。