原型模式

原型模式就是使用复制对象,创建出新的对象,并且不需要知道创建的细节(比如类的属性的赋值等等)。

基本使用(浅拷贝)

常见的就是使用Object的clone方法。需要让类实现Cloneable并重写clone方法,才能使用。

public class A implements Cloneable{private String code;private String name;public A(String code, String name) {this.code = code;this.name = name;}public void setCode(String code) {this.code = code;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}public static void main(String[] args) throws CloneNotSupportedException {A a = new A("00","name1");A a1 = (A)a.clone();a1.setCode("01");A a2 = (A)a.clone();a2.setCode("02");System.out.println(a.hashCode());System.out.println(a1.hashCode());System.out.println(a2.hashCode());}
}

结果,很明显,三个对象是不一样的。

596512129
824318946
930990596

深拷贝

上面那种方式,是浅拷贝,即只能拷贝A类中的基本数据类型和String。对于A类中如果还有其他引用类型,浅拷贝是实现不了引用类型的拷贝的。
所以,需要进行对A深拷贝B,通常有两种方法(重写Clone方法和序列化)。

方法1、重写A的clone方法,并在方法中对B进行拷贝(当然B类中也要实现浅拷贝)。

public class B implements Serializable,Cloneable{private String id;@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class A implements Serializable,Cloneable{private String code;private String name;private B b;public A(String code, String name, B b) {this.code = code;this.name = name;this.b = b;}public void setCode(String code) {this.code = code;}@Overridepublic Object clone() throws CloneNotSupportedException {A a = (A)super.clone();// 在A的clone方法中,对A的B引用进行clonea.b = (B)a.b.clone();return a;}public static void main(String[] args) throws CloneNotSupportedException {A a = new A("00","name1",new B());A a1 = (A)a.clone();a1.setCode("01");A a2 = (A)a.clone();a2.setCode("02");System.out.println(a.b.hashCode());System.out.println(a1.b.hashCode());System.out.println(a2.b.hashCode());}
}
执行结果:
596512129
824318946
930990596

看执行结果,每个A实例的B引用,都是不同的hashCode值,说明A中的B也被拷贝了。
如果将A中clone方法中的a.b = (B)a.b.clone();注释掉,可以得到最终打印出来的三个结果就是一样的。

方法2、序列化

序列化前提,A和B都要实现Serializable接口。
A和B的定义还是和方法1一样,我们只重写A中的clone方法。

@Overridepublic Object clone() throws CloneNotSupportedException {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);A copyResult = (A)ois.readObject();return copyResult;} catch (Exception e) {e.printStackTrace();}finally {try {bos.close();oos.close();bis.close();ois.close();} catch (IOException e) {e.printStackTrace();}}return null;}

最终效果也是随着A的clone,A中的B引用也被clone出新的一份来了。
上面的这个序列化只是一种实现思路,也可以用fastjson将A对象转成json字符串,再反转成A返回去,其实原理都是一样的。

实际应用场景

其实很好找,只要找到哪些类实现了Cloneable接口,大概率就是用到了所谓了原型模式。

比如Spring的Bean的创建,我都都知道默认是单例模式,那其实还可以知道Bean是多例的,这个就用到了原型模式。

[设计模式] ------ 原型模式(浅拷贝和深拷贝)相关推荐

  1. 【设计模式】原型模式 ( 浅拷贝 | 深拷贝 | 原型与单例冲突 | 禁用 final )

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

  2. Java常用设计模式————原型模式(一)

    介绍 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式用于创建重复的对象,同时又能保证性能.当直接创建对象的代价比较大时,则采用 ...

  3. C++设计模式——原型模式(Prototype Pattern)

    C++设计模式--原型模式(Prototype Pattern) 微信公众号:幼儿园的学霸 目录 文章目录 C++设计模式--原型模式(Prototype Pattern) 目录 定义 代码示例 普通 ...

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

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

  5. 设计模式 原型模式_创新设计模式:原型模式

    设计模式 原型模式 原型模式用于创建对象的副本. 这种模式非常有用,特别是当从头开始创建对象的成本很高时. 与builder , factory和abstract factory模式相比,它不会从头开 ...

  6. 设计模式 原型模式_设计模式:原型

    设计模式 原型模式 创新设计模式之一是原型设计模式 . 尽管原型是创造模式,但它在概念上与其他模式有所区别. 我的意思是原型在某种意义上创造了自己. 我将在下面解释. 原型模式的所有魔力都基于Java ...

  7. 设计模式 原型模式_原型设计模式:创建另一个小车

    设计模式 原型模式 创建对象确实是一个耗时的过程,也是一件昂贵的事情. 因此,我们现在正冒险节省时间和金钱. 我们该怎么做? 克隆奇迹多莉 有人记得多莉吗? 是的,是绵羊,是第一个被克隆的哺乳动物. ...

  8. 第六章 Caché 设计模式 原型模式

    文章目录 第六章 Caché 设计模式 原型模式 定义 使用场景 优点 结构图 描述 示例 初级写法 缺点 中级写法 缺点 高级写法 (浅复制) 浅复制 深复制 完整示例 简历类(复制类) 对象类(工 ...

  9. [设计模式]原型模式

    简介 原型模式 (Prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式是一种对象创建型模式 (可参考 设计模式 创建型模式). 结构 图-原型模式结构图 Pr ...

最新文章

  1. PHPCMS v9设置文章的审核功能
  2. TypeScript Partial 使用的一个小技巧
  3. 使用SQL Server分区表功能提高数据库的读写性能
  4. 在存储过程中编写正确的事务处理代码
  5. mrql初级教程-使用(er)
  6. axios的拦截器(Interceptors)
  7. C语言目录和文件操作扩展
  8. 关于SimpleITK 使用函数sitk.WriteImage报错‘ERROR (nifti_image_write_hdr_img2): cannot open output file ‘
  9. centos7下安装libiconv失败
  10. 简单的Site to site ipsec ×××实验
  11. 大数据分析对物联网发展有什么影响
  12. 邮箱发大文件服务器怎么删除,Exchange 2010如何删除系统默认邮箱数据库
  13. 在面试时应该如何自我介绍?
  14. 【产品经理】 产品经理进阶之路(十一):怎么看微信的公众号和百度的直达号,哪个更有优势
  15. 用Win32DiskImager写入U盘容量变小,恢复容量方法
  16. 中国IT工作者35岁后的发展出路调查报告(4)
  17. 三款ActiveX图表控件对比评测 Pro ActiveX、ProEssentials、ChartDirector
  18. LeetCode 2309. 兼具大小写的最好英文字母
  19. 韦东山第1期-学习笔记-2
  20. Android端乐橙云SDK集成

热门文章

  1. Java面试知识点:多态、内部类
  2. python 约束与异常处理
  3. python文件操作,自动关闭
  4. Python安装pip
  5. 编程面试题之——简答题(持续更新...)
  6. 解决PendingIntent传递参数为空的问题
  7. 图解JVM的Class文件格式(详细版)
  8. 在linux下添加路由
  9. JavaScript获取URL参数
  10. (转)Web Services使用多态(XmlInclude) ,支持自定义类型