文章目录
原型模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
优点 :
-
性能提高。
-
逃避构造函数的约束。
缺点:
-
配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
-
必须实现
Cloneable
接口。
使用场景 :
-
1、资源优化场景。
-
2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
-
3、性能和安全要求的场景。
-
4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
-
5、一个对象多个修改者的场景。
-
6、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
-
7、在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过
clone
的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。
注意事项
- 与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现
Cloneable
,重写,深拷贝是通过实现Serializable
读取二进制流。 Cloneable
接口克隆只能克隆引用,基础类型,String
类型,实际的Object
对象是不会克隆的
基本的克隆目标对象
public class DeepCloneableTarget implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
private String cloneName;
private String cloneClass;
//构造器
public DeepCloneableTarget(String cloneName, String cloneClass) {
this.cloneName = cloneName;
this.cloneClass = cloneClass;
}
//因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
深拷贝实现
public class DeepProtoType implements Serializable, Cloneable{
public String name; //String 属性
public DeepCloneableTarget deepCloneableTarget;// 引用类型
public DeepProtoType() {
super();
}
//深拷贝 - 方式 1 使用clone 方法
@Override
protected Object clone() throws CloneNotSupportedException {
//这里完成对基本数据类型(属性)和String的克隆
Object deep = super.clone();
//对引用类型的属性,进行单独处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
if (Objects.nonNull(deepCloneableTarget)) {
deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
}
return deepProtoType;
}
//深拷贝 - 方式2 通过对象的序列化实现 (推荐)
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);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e2) {
System.out.println(e2.getMessage());
}
}
return null;
}
}
测试
public class Client {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
DeepProtoType p = new DeepProtoType();
p.name = "宋江";
p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");
//方式1 完成深拷贝
DeepProtoType p2 = (DeepProtoType) p.clone();
System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
//方式2 完成深拷贝
DeepProtoType p3 = (DeepProtoType) p.deepClone();
System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
System.out.println("p3.name=" + p.name + "p3.deepCloneableTarget=" + p3.deepCloneableTarget.hashCode());
}
}
结果