简介
原型模式(Prototype Pattern)
是用于创建重复
的对象,同时又能保证性能
。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
模式结构
由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单,只需要实现Cloneable接口并重写clone()方法
- 模式的结构
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
- 模式的实现
原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。
public class PrototypePattern{
public static void main(String[] args) throws Exception{
Prototype prototype=new Prototype("zx",25);
Prototype clone=(Prototype) prototype.clone();
clone.setAge(28);
System.out.println(prototype);
System.out.println(clone);
}
}
//具体原型类
@Data
class Prototype implements Cloneable {
private String name;
private Integer age;
Prototype() {}
public Prototype(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("具体原型创建成功!");
}
public Object clone() throws CloneNotSupportedException{
System.out.println("具体原型复制成功!");
return (Prototype)super.clone();
}
}
- 优点
- 性能优良:原型模式是在内存二进制流的拷贝,要比new一个对象性能好很多,特别是在一个循环体类产生大量对象的时候更加明显。
- 逃避构造函数的约束:这是优缺点共存的一点,直接在内存中拷贝,构造函数是不会执行的
- 适用场景
- 资源初始化场景:类初始化需要消耗非常多的资源的时候。
- 性能和安全要求的场景:通过new产生一个对象需要非常繁琐的数据准备和访问权限的时候。
- 一个对象多个修改者的场景:一个对象需要提供给其他对象访问,而各个调用者可能都需要修改其值时考虑使用。
实际项目中原型模式很少单独出现,一般和工厂模式一起出现,通过clone方法创建一个对象,然后由工厂方法提供给调用者。
深拷贝、浅拷贝
- 浅克隆
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。Java中的浅复制通常使用clone()
方式完成。 - 深克隆
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。Java中通过对象的序列化和反序列化实现克隆
序列化实现深克隆
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
// 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
}