文章目录

  • I . 原型模式 总结
  • II . 原型模式 浅拷贝
  • III . 原型模式 深拷贝
  • IV . 原型模式 与 单例
  • V . 原型模式 中的 final 关键字 ( 禁止出现 )

I . 原型模式 总结


1 . 原型模式本质及性能 : 原型模式使用 clone 方法克隆对象 , 其本质是在内存中拷贝二进制数据 , 这种方式要比调用 new 构造函数性能高得多 ;

2 . clone 核心是内存拷贝 : clone 对象不使用复用原有对象 , 是在内存中的另一个地址空间复制了一份一模一样的数据 , 然后将其首地址给新对象的引用 ;

3 . 原型模式适用场景 : ① 节省资源 ( 内存 CPU 硬件等 ) , ② 构造函数复杂 ( 计算繁琐 耗时 ) , ③ 创建大量对象 ;

4 . 原型模式实现 : 原型模式类实现 Cloneable 接口 , 实现其中的 clone 方法 ;

① 浅拷贝实现 : 浅拷贝默认调用 super.clone ;

② 深拷贝实现 : 深拷贝需要调用 每个引用成员对象的 clone 方法创建成员对象 , 然后赋值给新的原型模式创建的对象 , 作为其中的成员 ;

5 . 注意拷贝方式 : 默认浅拷贝 , 如果类中有引用类型成员变量 , 需要考虑深拷贝问题 , 可能会出现多个对象持有同一个引用变量 ;

II . 原型模式 浅拷贝


1 . 浅拷贝 : 调用 clone 对象拷贝内存中的数据时 , 要注意拷贝的是基础数据类型 , 对于数组 , 集合 , 自定义类等引用数据类型仅拷贝地址 , 会造成所有的对象都持有同一个内存地址的引用成员 ;

① 基础数据类型 : 如果类中全部是基础数据类型 , 使用 clone 可以将该类完整的复制一份 ;

② 引用数据类型 : 如果类中有引用类型成员 , 只是拷贝该成员的地址 , 所有的拷贝创建的原型模式实例对象都持有同一个引用 , 如果修改该引用成员的值 , 所有的原型对象实例的值都会跟着修改 ;

2 . 浅拷贝示例 :

① 原型模式类 Student : 该类中持有 Vector<String> courses 引用数据类型 , 调用 clone 方法在内存中复制对象时 , 仅复制了对象的地址 , 即将该引用的地址赋值给了 clone 出的对象 ;

package kim.hsl.design.prototype.shallowcopy;import java.util.Vector;/*** 浅拷贝示例*/
public class Student implements Cloneable {private String name;private int age;//该类在拷贝时 , 如果使用浅拷贝 , 只是将地址拷贝走了 , 两个对象实际上用的是同一个对象private Vector<String> courses = new Vector<>();public Student() {System.out.println("调用 Student 默认构造函数");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Vector<String> getCourses() {return courses;}public void setCourses(Vector<String> courses) {this.courses = courses;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", courses=" + courses +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {System.out.println("调用 Student clone 方法");return super.clone();}
}

② 测试类 Main : 此处创建了两个 Student 实例对象 , 但是两个对象都持有同一个 Vector<String> courses 引用数据类型成员 , 当修改其中一个成员时 , 两个对象中的该成员都会改变 ;

package kim.hsl.design.prototype.shallowcopy;public class Main {public static void main(String[] args) {try {//测试使用 clone 方法实现的原型模式 , 使用原型模式创建 2 个对象Student newStudent = new Student();// 1 . 使用 clone 方法创建对象1Student student = (Student) newStudent.clone();student.setName("Tom");student.setAge(10);student.getCourses().add("数学");// 2 . 使用 clone 方法创建对象2Student student2 = (Student) newStudent.clone();student2.setName("Jerry");student2.setAge(18);student2.getCourses().add("语文");System.out.println("student : " + student + "\nstudent2 : " + student2);} catch (CloneNotSupportedException e) {//捕获 clone 方法可能产生的异常e.printStackTrace();}}
}

③ 执行结果 : 调用第一个对象 add 方法 , 在 vector 集合中添加了 “数学” 字符串 , 调用第二个对象的 add 方法 , 向 courses 集合中添加 “语文” 字符串 , 理论上两个分别是 “数学” 和 “语文” , 但是此处却都变成了 “数学” “语文” 两个课程 , 说明两个原型模式对象持有的 Vector<String> courses 变量是指向同一个内存地址的 ;

调用 Student 默认构造函数
调用 Student clone 方法
调用 Student clone 方法
student : Student{name='Tom', age=10, courses=[数学, 语文]}
student2 : Student{name='Jerry', age=18, courses=[数学, 语文]}

III . 原型模式 深拷贝


1 . 深拷贝策略 : 深拷贝时需要在 clone 方法中 , 调用引用数据类型本身的 clone 对象 , 在将其赋值给被拷贝的原型模式实例对象 ;

2 . 深拷贝 clone 方法流程 :

① 创建实例对象 : 通过 clone 方法 , 创建原型模式类的实例对象 , 此时该对象的引用成员处于浅拷贝状态 ;

② 拷贝引用成员 : 调用原型模式类对象成员的 clone 对象 , 创建新的成员对象 , 将新的成员对象赋值给克隆出的原型模式对象 ;

③ 返回新的对象 : 返回 clone 创建的原型模式实例对象 ;

3 . 示例代码 :

① 原型模式深拷贝示例 : 深拷贝与浅拷贝只是在 clone 方法中表现不同 , 其它代码一致 ; 在 clone 方法中需要针对引用类型进行克隆 ;

package kim.hsl.design.prototype.deepcopy;import java.util.Vector;/*** 浅拷贝示例*/
public class Student implements Cloneable {private String name;private int age;//该类在拷贝时 , 如果使用浅拷贝 , 只是将地址拷贝走了 , 两个对象实际上用的是同一个对象private Vector<String> courses = new Vector<>();public Student() {System.out.println("调用 Student 默认构造函数");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Vector<String> getCourses() {return courses;}public void setCourses(Vector<String> course) {this.courses = course;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", course=" + courses +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {System.out.println("调用 Student clone 方法");//1 . 首先拷贝一个基本对象Student student = (Student) super.clone();//2 . 将引用类型的对象单独克隆赋值student.courses = (Vector<String>) this.courses.clone();//3 . 返回创建的新的对象return student;}
}

② 测试代码 :

package kim.hsl.design.prototype.deepcopy;public class Main {public static void main(String[] args) {try {//测试使用 clone 方法实现的原型模式 , 使用原型模式创建 2 个对象Student newStudent = new Student();// 1 . 使用 clone 方法创建对象1Student student = (Student) newStudent.clone();student.setName("Tom");student.setAge(10);student.getCourses().add("数学");// 2 . 使用 clone 方法创建对象2Student student2 = (Student) newStudent.clone();student2.setName("Jerry");student2.setAge(18);student2.getCourses().add("语文");System.out.println("student : " + student + "\nstudent2 : " + student2);} catch (CloneNotSupportedException e) {//捕获 clone 方法可能产生的异常e.printStackTrace();}}
}

③ 运行结果 : 原型模式的两个实例对象的互不干扰 ;

调用 Student 默认构造函数
调用 Student clone 方法
调用 Student clone 方法
student : Student{name='Tom', age=10, course=[数学]}
student2 : Student{name='Jerry', age=18, course=[语文]}

IV . 原型模式 与 单例


1 . 原型模式 与 单例模式 :

① 原型模式 : 原型模式的核心是不调用构造函数 , 使用 clone 方法在内存中克隆对象 ;

② 单例模式 : 单例模式的核心是私有化构造函数 , 控制外部用户 , 不能随意调用构造函数创建对象 ;

2 . Cloneable 破坏了单例模式 : 此处二者就出现了矛盾 , 如果单例类 , 实现了 Cloneable 接口 , 那么该类就可以调用 clone 方法创建另外的实例对象 , 因此破坏了单例模式 ;

3 . 解决方案 :

① 不实现 Cloneable 接口 : 单例模式中不要实现 Cloneable 接口 , 不提供内存拷贝功能 ;

② clone 中调用单例 : 如果必须实现 Cloneable 接口 , 那么在重写的 clone 方法中 , 调用获取单例类的方法 , 不要进行内存对象拷贝创建新的实例对象 ;

V . 原型模式 中的 final 关键字 ( 禁止出现 )


1 . final 作用 : final 用于修饰常量 , 被 final 修饰的变量无法重新赋值 ;

2 . Cloneable 实现类成员不要使用 final : 在原型模式的类中 , 实现了 Cloneable 接口 , 重写了 clone 方法 , 其类对象的成员不能被 final 修饰 , 否则无法重新赋值 ;

【设计模式】原型模式 ( 浅拷贝 | 深拷贝 | 原型与单例冲突 | 禁用 final )相关推荐

  1. 原型模式与深拷贝浅拷贝

    原型模式与深拷贝浅拷贝 原型模式 Java中的原型模式 简单的例子 浅拷贝 深拷贝 效率比较 JMH测试样例 测试结果 原型模式 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或 ...

  2. 设计模式理解(二)创建型——单例、原型

    设计模式理解(二)单例(Singleton)与原型(Prototype) 为什么一起写,因为懒.... 单例,就是用了面向对象语言的一些奇技淫巧,把构造函数私有了,然后用一个自身类型的静态指针作为全局 ...

  3. 原型模式——java实现原型模式的几种写法

    原型模式综述   原型设计模式的本质就是复制一个和自己一样的对象,这个一样指的是数据字段(feild)的一样,并且当原来的对象发生变化的时候,复制出来的对象应该是不能改变的,也就是要进行深度的克隆.j ...

  4. 设计模式 状态模式 以自动售货机为例

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/26350617 状态模式给了我眼前一亮的感觉啊,值得学习~ 先看定义:允许对象在内 ...

  5. 设计模式-原型模式(克隆羊多利看了都说好)

    文章目录 引例 原型模式 浅拷贝 深拷贝 引例 标题无意冒犯 在介绍原型模式前,我们先从实际问题出发,对比解决方法前后优劣点. 问题: 现在有一只羊(包含属性:名字Dolly.年龄2),需要克隆10只 ...

  6. 设计模式之【原型模式】,深入理解深拷贝与浅拷贝

    文章目录 一.什么是原型模式 二.原型模式实现方式 1.传统方式 2.原型模式 熟悉浅拷贝和深拷贝 浅拷贝实现对象克隆 深拷贝实现对象克隆 一.什么是原型模式 原型模式: 用一个已经创建的实例作为原型 ...

  7. 2.5万字详解23种设计模式—创建型模式(简单工厂、工厂方法、抽象工厂、单例-多线程安全详解、建造者、原型)的详细解读、UML类图

    本文简述了各大设计模式,并通过UML和代码详细说明.本文大约共 2.5W 字,建议收藏.下方是本文的目录: 一.设计模式的认识 二.设计模式的分类 根据其目的 根据范围 三.设计模式的优点 四.设计模 ...

  8. 设计模式【5】-- 原型模式

    开局一张图,剩下全靠写- 设计模式文章集合:http://aphysia.cn/categories/designpattern 前言 接触过 Spring 或者 Springboot 的同学或许都了 ...

  9. 一口气讲完设计模式(单例模式、工厂模式、原型模式、建造者模式、适配器、桥梁模式)

    设计模式 使用设计模式,可以让我们的代码具有更好的可读性.可扩展性.可读性.重用性.符合高内聚低耦合的特点.作为程序员,是我们经常听到的概念,也是我们程序员必须深入学习,了解的知识. 设计模式种类 该 ...

最新文章

  1. 实操教程|使用图像分割来做缺陷检测的一个例子
  2. 数据结构面试的常客,一文带你深入了解堆
  3. python添加系统环境win7_python环境配置(基于win7 x64)
  4. QEMU-KVM中的多线程压缩迁移技术
  5. python简单的监控脚本-利用socket、psutil阻止远程主机运行特定程序
  6. 计算机操作系统的新技术新知识,计算机操作系统教程:核心与设计原理
  7. layui 加载第三方插件
  8. [转]VirtualBox安装CentOS7
  9. HDOJ 5184 Brackets 卡特兰数扩展
  10. kubernetes1.4新特性:支持两种新的卷插件
  11. mysql 使用concat模糊查询
  12. linux系统时间和硬件时钟问题
  13. php 刷新腾讯云cdn
  14. 激光打标二代激光卡工控机装机指引
  15. python的多行注释以什么开头_Python的多行注释
  16. 链表的节点与指针 (重新理解)
  17. 消息队列(MQ)之生产者-消费者 | 一文搞定
  18. 亚马逊资源名称 (ARN) 和 AWS 服务命名空间
  19. CI持续集成系统环境--Gitlab+Gerrit+Jenkins完整对接
  20. 监控告警 Metrics - Prometheus

热门文章

  1. Sqlserver 优化的方法
  2. Postman使用方法示例
  3. PB初体验 class one
  4. [py]django url 参数/reverse和HttpResponseRedirect
  5. 【调查】您对计算机培训感兴趣吗?
  6. celery的log如何传递给django,由django管理
  7. sqlserver 查询语句执行历史
  8. 面向对象(静态变量和成员变量的区别)
  9. java.lang.IllegalAccessError: org.apache.commons.dbcp.DelegatingPreparedStatement.isClosed()Z
  10. 创建 Java 第三方类库,以及制作类库的Javadoc