原型模式是一种创建型设计模式,它允许一个对象再创建另一个可定制的对象,根本无需知道任何创建的细节。

定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

问题描述:创建一个重复的结构复杂的对象时的成本比较大,比如细胞分裂、新建一个模板等。

解决方案:将这个结构复杂的对象作为一个原型,然后通过复制这个原型对象来创建更多同类型的对象。

结构图:

说明:

(1)抽象原型类(Cloneable):这是一个抽象角色,可用接口或抽象类来实现,这里声明了一个克隆的方法,是所有具体原型类共同拥有的父类或接口;

(2)具体原型类:继承或实现抽象原型类的克隆方法,返回自己的一个克隆对象;

(3)使用者(User):让一个已有的原型对象通过调用其克隆方法,获得该对象的克隆对象。

举个栗子:讲一个孙悟空拔毛变小猴儿的故事,将孙悟空作为一个原型对象,克隆出不同的小猴儿,使用原型模式来实现。

1. 新建一个原型类MonkeyPrototype,实现Cloneable接口中的clone()方法,返回自己的一个克隆对象,其中引用了Address对象。代码如下:

2. 在类PrototypeFragment中使用一个已有的原型对象,通过调用其克隆方法获得该对象的克隆对象,并对克隆对象的名字name和地址address进行更改。代码如下:

4. 运行后的效果,如图所示:

上面的实现方式叫作浅克隆,它只能克隆对象本身,对于依附于对象的对象则不予克隆,只对其地址克隆。栗子中,Address就是依附于原型类MonkeyPrototype的对象的对象,只克隆了它的引用地址,当克隆对象monkey_A对地址做出改动时,比如将“花果山”改为“峨眉山”,原型对象和克隆对象的地址都发生了改变。也就是说,如果原型对象的成员变量是值类型,则进行复制,不会互相影响;如果是引用类型,比如Address,则将其地址复制,实质上指向的是同一个对象。

浅克隆需要注意的地方:

(1)被克隆的对象需要实现需要实现Cloneable;

(2)要重写clone() 方法;

(3)对于依附于被克隆对象的对象,只克隆其地址。一旦更改都会改变。

下面用深克隆来实现原型模式。具体实现方式如下:

1. 让原型类MonkeyPrototype实现可序列化接口Serializable,增加一个deepClone()方法。代码如下:

2. 在类PrototypeFragment中仍然使用这个已有的原型对象,通过调用deepClone()方法对该对象的进行深克隆,并对克隆对象的名字name和地址address进行更改。代码如下:

3. 运行后的效果,如图所示:

由上可知,深克隆利用了IO流进行存储,然后进行读取,不仅对克隆对象进行克隆,而且对其依附着的对象也进行了克隆。如栗子所示,原型猴儿携带的信息包含孙悟空、六耳猕猴和峨眉山,深克隆后的对象是猴儿B,我更改了名字和地址,其中名字name是值类型成员变量,则复制后改变不会影响原型对象的值,地址address是引用类型成员变量,因为是深克隆,所以也复制了一份给克隆对象,所以更改后也将不会影响到原型对象中的地址值。

深克隆,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象。

深克隆需要注意的地方:

(1)利用IO流进行存储,然后进行读取;

(2)需要实现可序列化接口Serializable。

优点:

(1)当创建一个结构复杂的对象时,原型模式可以简化其创建过程,通过复制已有的实例来获得相同的对象;

(2)简化创建结构,不需要专门的工厂存在,仅需要实现克隆方法即可。

缺点:

(1)必须实现Cloneable接口;

(2)逃避构造函数的约束;

(3)克隆方法在类的内部,加重类的职责,当需要对已有类进行改造时需要修改原型类。

使用场景:

(1)当创建成本比较大的时候,新的对象可以使用原型模式来获得;

(2)系统要保存对象的状态,并且对象本身占用内存很少,比如要恢复到某个时间的某种状态,可以使用原型模式配合备忘录模式来实现。

java与模式孙悟空_设计模式之原型模式 - chenxkang的个人空间 - OSCHINA - 中文开源技术交流社区...相关推荐

  1. java顺序表冒泡排序_冒泡排序就这么简单 - Java3y的个人空间 - OSCHINA - 中文开源技术交流社区...

    冒泡排序就这么简单 在我大一的时候自学c语言和数据结构,我当时就接触到了冒泡排序(当时使用的是C语言编写的).现在大三了,想要在暑假找到一份实习的工作,又要回顾一下数据结构与算法的知识点了. 排序对我 ...

  2. java拆分任意五位数_五位数拆分出各位 - osc_foo7glsg的个人空间 - OSCHINA - 中文开源技术交流社区...

    5.输入一个五位数,输出一个反转的五位数 输入->12345 输出->54321 //这是五位数字拆分方法. System.out.println("请输入五位数的数字:&quo ...

  3. ie对java的设置字体_关于IE6幽灵字体 - JavaSwing的个人空间 - OSCHINA - 中文开源技术交流社区...

    前言:今天做项目的时候在IE6下出现了这样的一种现像,这种情况只在IE6下出现,最后在网友的帮助下这个问题最终得到了解决.所以马上作了下笔记! 情况如下图: 我在网上找了点资料出现IE6下幽灵字体的情 ...

  4. java 全排列非递归算法_全排列的非递归算法 - osc_ivkc73ze的个人空间 - OSCHINA - 中文开源技术交流社区...

    1.全排列的定义和公式: 从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列.由排列的定义,显然不同的顺序是一个不同的排列.从n个元素中取m个元素 ...

  5. java 滚动加载_滚动加载 - java-苦苦甜甜的个人空间 - OSCHINA - 中文开源技术交流社区...

    html代码如下: 滚动条距离底部 #parse("front/common/include.html") $(function () { var i = 4; $(window) ...

  6. Java实现数组列项相加_裂项求和法 - osc_rkun22vq的个人空间 - OSCHINA - 中文开源技术交流社区...

    常用公式 常用式:$\cfrac{1}{n(n+1)}=\cfrac{1}{n}-\cfrac{1}{n+1}$:推广式:$\cfrac{1}{n(n+k)}=\cfrac{1}{k}(\cfrac{ ...

  7. java如何测试定时器_如何测试定时任务 - 邓竣的个人页面 - OSCHINA - 中文开源技术交流社区...

    系统一般会有一些后台定时任务,假设我们使用quartz实现定时任务,那么有两个测试功能点: 定时任务逻辑是否正确 定时器cron表达式编写是否正确,触发时间点是否正确 定时任务逻辑测试 如果定时任务在 ...

  8. Java位语句_卫语句 - 宿小帅的个人空间 - OSCHINA - 中文开源技术交流社区

    1.使用卫语句取代嵌套表达式 函数中的条件逻辑使人难以看清正常的执行途径.使用卫语句表现所有特殊情况. 动机:条件表达式通常有2种表现形式.第一:所有分支都属于正常行为.第二:条件表达式提供的答案中只 ...

  9. java树莓派温度传感器_树莓派传感器篇 - 枫TI的个人空间 - OSCHINA - 中文开源技术交流社区...

    玩树莓派其中方向之一:控制各种传感器.先搞明白各种传感器的参数及使用方式.树莓派GPIO各个引脚的用处及含义,这里要着重说明一点的是:千万不要把3.3V以上的电压链接到树莓派的引脚上,千万不要把3.3 ...

  10. java痴和堆_JAVA虚拟机理解 - 爱笑的痴迷者的个人空间 - OSCHINA - 中文开源技术交流社区...

    JVM定义: JVM(Java Virtual Machine),是一种运行Java程序的软件实现,是虚拟的机器.Java程序与平台无关,它直接在虚拟机中运行. JVM运行过程: JVM将内存分划如下 ...

最新文章

  1. 客快物流大数据项目(二十二):Docker环境中安装软件
  2. 预计2024年全球医疗AI市场超100亿美元
  3. PaddleOCR加载chinese_ocr_db_crnn_server/chinese_ocr_db_crnn_modile模型进行中英文混合预测(代码)实践
  4. java渡劫期(32)----java进阶(ssm整合项目实战----房屋出租系统(渡劫失败))
  5. python网络编程爬虫_Python爬虫--网络编程
  6. 【实用工具】adb检测android设备
  7. 大数据之Hadoop图解概述
  8. MacOS Ventura 13.0.1 (22A400) 正式版带 OC 0.8.6 and winPE 双分区原版黑苹果镜像
  9. 淘宝客用微博推广方法
  10. 支付宝支付服务端对接记录(小程序/APP 预支付统一下单及回调处理)
  11. OCCT示例学习笔记3--Modeling项目
  12. 解析 embedded.mobileprovision 获取信息
  13. Office快捷键大全之二(Excel快捷键)
  14. Centi和HandCash共同开发支付握手协议
  15. (十一)java.io.File学习进阶及separator、pathSeparator分隔符简介
  16. C语言数字图像处理---1.5图像基本变换之平移缩放旋转
  17. 三人表决电路——Verilog HDL语言
  18. 在前端页面生成二维码并下载(兼容IE)
  19. C语言讲义——头文件
  20. 基于Web标准的网页设计与制作知识整理

热门文章

  1. java 读取gzip_Java读取GZIP
  2. 采用计算机对酒店客房进行管理,酒店客房管理系统—计算机毕业设计论文.doc...
  3. 【读书笔记】计算广告(第3部分)
  4. python实现wifi自动连接,解决电脑wifi经常断开的问题
  5. 请教各位大虾:Delphi创建的ActiveForm上的SpeedButton在鼠标离开后没有重画为flat样式
  6. 【Windows Server 2019】活动目录 (Active Directory) ——创建、删除和管理对象、容器和组织单位(OU)
  7. 题解 P2916 【[USACO08NOV]安慰奶牛Cheering up the Cow】
  8. idea创建Springboot项目时,出现Error:java: 读取C:\Users\HP\.m2\repository\com\vaadin\external\google\android-js
  9. php 图形库 锯齿,PHP imageantialias - 是否使用抗锯齿(antialias)功能 - 有码中国
  10. word---尾注法插入参考文献