定义
原型模式(Prototype Design Pattern)用一个已经创建的实例作为原型,通过复制改原型对象来创建和原型对象相同的新对象。
原型模式前段的js用的比较多
浅克隆
克隆对象中的所有变量的值与原型对象的值完全相同(引用数据类型变量存储的地址也是完全一致的)
定义原型类
- Person类
package com.imysh.zmy.mca.designpattern.prototype.example01;
/**
* @author zhangmy
* @date 2023/2/2 14:01
* @description
*/
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
}
- 原型类
package com.imysh.zmy.mca.designpattern.prototype.example01;
/**
* @author zhangmy
* @date 2023/2/2 13:46
* @description 具体的原型对象
*/
public class ConcretePrototype implements Cloneable {
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public ConcretePrototype() {
System.out.println("创建原型对象成功");
}
public ConcretePrototype(Person person) {
System.out.println("创建原型对象成功");
this.person = person;
}
@Override
protected ConcretePrototype clone() throws CloneNotSupportedException {
System.out.println("开始克隆对象...");
return (ConcretePrototype)super.clone();
}
}
- 测试类
/**
* 浅拷贝测试
* @throws CloneNotSupportedException
*/
public static void shallowTest() throws CloneNotSupportedException {
Person p1 = new Person("张三");
ConcretePrototype c1 = new ConcretePrototype(p1);
ConcretePrototype c2 = c1.clone();
Person p2 = c2.getPerson();
p2.setName("李四");
System.out.println("原型模式浅克隆c1对象和c2对象是同一个对象吗?" + (c1 == c2));
System.out.println("原型模式浅克隆p1对象和p2对象是同一个对象吗?" + (p1 == p2));
}
浅克隆的结果可以看出虽然克隆出来的对象不是同一个,但是内部的变量的值(p1、p2)都是同一个对象
深克隆
克隆对象的所有基本类型变量含有的值与原型对象完全一致(不包含引用数据类型)
深克隆需要用到序列化流的方式,这里我们将Person类和ConcretePrototype类实现序列化接口Serializable
然后修改一下复制的代码
/**
* 深拷贝测试
*/
public static void deepTest() throws IOException, ClassNotFoundException {
Person p1 = new Person("张三");
ConcretePrototype c1 = new ConcretePrototype(p1);
// 创建对象序列化输出流
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("a.txt"));
// 写入文件
outputStream.writeObject(c1);
outputStream.close();
// 创建对象序列化输入流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("a.txt"));
// 读取文件
ConcretePrototype c2 = (ConcretePrototype)inputStream.readObject();
inputStream.close();
Person p2 = c2.getPerson();
p2.setName("李四");
System.out.println("原型模式浅克隆c1对象和c2对象是同一个对象吗?" + (c1 == c2));
System.out.println("原型模式浅克隆p1对象和p2对象是同一个对象吗?" + (p1 == p2));
}
可以看到内部对象属性person已经不是同一个对象了
原型模式的核心是克隆,浅拷贝有Object的clone() 方法(基于二级制),深拷贝的话可以使用Hutool的BeanUtil.copyProperties()方法去克隆属性。另外原型模式可以用在一些使用模板的场景(模板对象拷贝,然后填充部分变量即可),数据备份、撤销的场景、资源优化场景(IO、CPU)、复杂的依赖场景(级联依赖)、性能和安全要求的场景、同一个对象被多个修改者使用的场景等等
评论区