原型模式(Prototype Pattern)指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象,属于创建型设计模式。
    以系统中已经存在的对象为原型,直接基于内存二进制流进行复制,不会调用构造函数,也不需要再进行初始化的过程,大大缩短创建时间。

    使用场景
    (1)创建对象成本较大(例如,初始化时间长,占用CPU太多,或者占用网络资源太多等),需要优化资源。
    (2)创建一个对象需要烦琐的数据准备或访问权限等,需要提高性能或者提高安全性。
    (3)一个对象被多个修改者修改。系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值。每个修改者自己克隆一个拷贝,然后修改拷贝。

    实现方式:
    实现Cloneable接口,重写clone()方法。如果没有实现Cloneable接口,调用clone方法会抛出CloneNotSupportedException异常。

    浅拷贝
    基础数据类型会被拷贝,数组和引用对象指向相同的实例,只是指针拷贝了副本,复制了引用的地址
    Cloneable接口的clone方法是浅拷贝
    深拷贝
    基础数据类型会被拷贝,数组和引用对象指向不同的实例,实例的值进行了拷贝

    • 序列化后反序列化
    • 重写clone方法,手动给克隆对象的相关属性分配另一块内存
    1. public class MyPrototype implements Cloneable, Serializable {
    2. private String code;
    3. private List<String> list;
    4. @Override
    5. public MyPrototype clone() {
    6. try{
    7. return (MyPrototype)super.clone();
    8. }catch (CloneNotSupportedException e){
    9. e.printStackTrace();
    10. return null;
    11. }
    12. }
    13. public MyPrototype deepClone(){
    14. try{
    15. //设置写缓冲
    16. ByteArrayOutputStream bos = new ByteArrayOutputStream();
    17. ObjectOutputStream oos = new ObjectOutputStream(bos);
    18. //往写缓冲中写入
    19. oos.writeObject(this);
    20. //写缓冲中复制到读缓冲
    21. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    22. ObjectInputStream ois = new ObjectInputStream(bis);
    23. //从读缓冲中读取
    24. return (MyPrototype)ois.readObject();
    25. } catch (Exception e) {
    26. e.printStackTrace();
    27. return null;
    28. }
    29. }
    30. ...
    31. }

    框架:
    spring的@Scope(“prototype”)
    反序列化JsonObject.parseObject()

    原型模式的优点

    1. Java自带的原型模式基于内存二进制流的复制,不会进行初始化, 不会执行构造函数, 在性能上比直接new一个对象更加优良。
    2. 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

    原型模式的缺点

    1. 需要为每一个类都配置一个clone方法。
    2. clone方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
    3. 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。