zoukankan      html  css  js  c++  java
  • 原型模式

    一、概念

    原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。(创建型模式。简单来说,就是用于复制对象)

    在Spring中,原型模式应用得非常广泛。例如 scope=“prototype”,我们经常用的JSON.parseObject()也是一种原型模式。

    我们拿电脑中的复制粘贴的例子来演示一下原型模式: 

    上面这张图已经很明显了,我们首先需要一个文件,该文件一定要有可以被克隆的功能,那么我们创建这个文件后,就可以通过它克隆无数个。

    下面是原型模式的类结构图:

    二、适用场景

    • 类初始化消耗资源较多
    • new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
    • 构造方法比较复杂
    • 循环体中生产大量对象时

    三、模拟原型模式

    ① 先声明一个克隆自身的原型Prototype接口:

    ② 创建具体需要克隆的对象ConcretePrototype:

    ③ 定义一个Client类,用于测试克隆对象:

    上面实际上,把new用代码隐藏了,本质上对象的产生还是靠new产生的,只是耐看了一些,具备了原型模式的形态,但产生的对象并不能直接复制对象的当前运行状态(每拷贝一次对象,需要走一次构造方法),所以需要做一些改进。

    四、真正原型模式

    • 只有实现了Cloneable这个接口的类才可以被拷贝
    • 拷贝得到的是一个新的对象,但是这个新对象的内容是拷贝对象的当前运行时内容
    • 在拷贝对象的过程中,没有调用构造方法(new的时候,JVM要走一趟类加载流程,这个流程非常麻烦,会调用构造方法,再把最后生成的对象放到堆中。而Object类的clone()方法原理:JVM从堆内存中以二进制流的方式进行拷贝,重新分配一个内存块,将对象当前内存状态拷贝到新开辟的内存中)
    • 拷贝分为浅拷贝深拷贝,主要区别在于是否支持对象引用类型的成员变量的拷贝

    1、浅拷贝:只会拷贝基本数据类型(也包括String),对于对象属性只拷贝其中的引用地址。

    例子:① 定义一个Student类,实现Cloneable接口,重写clone()方法。

    ② 测试代码:

    ③ 运行结果:

    分析:从测试结果可以看出,String[]对象没有被拷贝,拷贝的只是对象引用的地址。因此,如果我们修改任意一个对象类型的成员变量的属性值,比如上图中的hobbies值,则所有拷贝的hobbies值都会改变,这就是浅拷贝。

    下面这张图,对象引用的地址指向堆内存中的对象实例:

    2、深拷贝:不仅能够拷贝基本数据类型,还能拷贝对象引用类型(包括数组、容器、引用对象等)。

    例子:① 还是原来的Student类,现在对clone()方法中的逻辑做一些修改。

    ② 测试代码:

    ③ 运行结果:

    分析:从测试结果可以看出,String[]对象在内存中被拷贝。因此,如果要实现深拷贝,必须将原型中的数组、容器对象、引用对象等另行拷贝(这些引用对象也要实现Cloneable接口)。

    五、拷贝破坏单例模式

    提问:如果我们深拷贝的目标对象是单例对象,那意味着,深拷贝就会破坏单例,怎么办?

    实际上防止拷贝破坏单例的解决思路很简单:

    ① 禁止深拷贝即可

    ② 单例类不实现Cloneable接口

    ③ 如果非要实现Cloneable接口,那么可以重写clone()方法,在方法中返回单例对象即可,如下:

    六、在源码中的应用

    我们常用的ArrayList就实现了Cloneable接口,重写clone()方法,源码如下:

  • 相关阅读:
    PAT (Advanced Level) Practice 1100 Mars Numbers (20分)
    PAT (Advanced Level) Practice 1107 Social Clusters (30分) (并查集)
    PAT (Advanced Level) Practice 1105 Spiral Matrix (25分)
    PAT (Advanced Level) Practice 1104 Sum of Number Segments (20分)
    PAT (Advanced Level) Practice 1111 Online Map (30分) (两次迪杰斯特拉混合)
    PAT (Advanced Level) Practice 1110 Complete Binary Tree (25分) (完全二叉树的判断+分享致命婴幼儿错误)
    PAT (Advanced Level) Practice 1109 Group Photo (25分)
    PAT (Advanced Level) Practice 1108 Finding Average (20分)
    P6225 [eJOI2019]异或橙子 树状数组 异或 位运算
    P4124 [CQOI2016]手机号码 数位DP
  • 原文地址:https://www.cnblogs.com/ZekiChen/p/12492959.html
Copyright © 2011-2022 走看看