原型模式(Prototype Pattern) ,是 GoF 的 23 种设计模式的一种,是用于创建重复的对象,同时又能保证性能。属于创建型模式,提供创建对象的最佳方式。
原型(Prototype),在制造业中通常是指大批量生产开始之前研发出的概念模型,并基于各种参数指标对其进行检验,如果达到了质量要求,即可参照这个原型进行批量生产。原型模式达到以原型实例创建副本实例的目的即可,并不需要知道其原始类,也就是说,原型模式可以用对象创建对象,而不是用类创建对象,以此达到效率的提升。
~
本篇内容包括:关于原型模式、原型模式-浅拷贝实现、原型模式-深拷贝实现
原型模式(Prototype Pattern) ,是 GoF 的 23 种设计模式的一种,是用于创建重复的对象,同时又能保证性能。属于创建型模式,提供创建对象的最佳方式。
原型(Prototype),在制造业中通常是指大批量生产开始之前研发出的概念模型,并基于各种参数指标对其进行检验,如果达到了质量要求,即可参照这个原型进行批量生产。原型模式达到以原型实例创建副本实例的目的即可,并不需要知道其原始类,也就是说,原型模式可以用对象创建对象,而不是用类创建对象,以此达到效率的提升。
原型模式包含如下角色:
原型模式的使用需要注意浅拷贝与深拷贝的问题
浅拷贝,即调用 clone 对象拷贝内存中的数据时,要注意拷贝的是基础数据类型,对于数组,集合,自定义类等引用数据类型仅拷贝地址,会造成所有的对象都持有同一个内存地址的引用成员。
# Cloneable 抽象原型类
Java 中的 Object 类中提供了 clone() 方法来实现浅克隆。 Cloneable 接口是可以看作抽象原型类,而实现了 Cloneable 接口的子实现类就是具体的原型类
# Realizetype 具体原型类
public class Realizetype implements Cloneable {
private Integer a;
private Integer b;
public Integer getA() {
return a;
}
public void setA(Integer a) {
this.a = a;
}
public Integer getB() {
return b;
}
public void setB(Integer b) {
this.b = b;
}
public Realizetype() {
System.out.println("具体的原型对象创建完成!");
}
@Override
protected Realizetype clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功!");
return (Realizetype) super.clone();
}
}
# Client 访问测试类
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Realizetype r1 = new Realizetype();
r1.setA(10);
r1.setB(11);
Realizetype r2 = r1.clone();
// 两者数据分别为 false 和 true 对象都持有同一个内存地址的引用成员
System.out.println("对象r1和r2是同一个对象?" + (r1 == r2));
System.out.println("对象r1和r2是同一个对象?" + (r1.getA() == r2.getA()));
}
}
深拷贝,深拷贝时需要在 clone 方法中 , 调用引用数据类型本身的 clone 对象 , 在将其赋值给被拷贝的原型模式实例对象。
实现深拷贝有两种方法:
序列化该对象,然后反序列化回来,就能得到一个新的对象了。
序列化:将对象写入到IO流中; 反序列化:从IO流中恢复对象 序列化机制允许将实现序列化的java对象转化为字节序列,这些字节序列可以保存到磁盘或者网络传输上,以达到以后恢复成原来的对象,序列化机制使得对象可以脱离程序的运行而独立存在。
继续利用 clone()
方法,对该对象的引用类型变量再实现一次 clone()
方法。
这里我们使用序列化的方式来实现深拷贝
# Realizetype 实现 Serializable 序列化接口
# Client
import java.io.*;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Realizetype r1 = new Realizetype();
r1.setA(10);
r1.setB(11);
//创建对象输出流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/Users/lizhengi/test/b.txt"));
//将c1对象写出到文件中
oos.writeObject(r1);
oos.close();
//创建对象出入流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/Users/lizhengi/test/b.txt"));
//读取对象
Realizetype r2 = (Realizetype) ois.readObject();
// 两者数据都为 false 说明对象持有不同的内存地址的引用成员,完成深拷贝
System.out.println("对象r1和r2是同一个对象?" + (r1 == r2));
System.out.println("对象r1和r2是同一个对象?" + (r1.getA() == r2.getA()));
}
}