【设计模式 06】原型模式(克隆??)

原型模式(clone?)

Prototype pattern refers to creating duplicate object while keeping performance in mind. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.

参考:

  1. tutorialspoint | prototype_pattern
  2. 博客园 | 原型模式
  3. 博客园 | Java深拷贝与序列化

原型模式是通过复制已有对象来快速创建新对象的方法,它适用于创建那些实例化很慢的对象,比如数据库连接对象,在创建好这样的对象后,我们可以缓存一份,下次需要这种对象时,我们可以直接返回一个该对象的拷贝。

使用场景

  1. 需要大量相似对象时,如果在类中需要大量相似的对象,并且这些对象中有很多属性都是一样的,只有个别属性需要定制时,可以使用原型模式,因为直接从内从中复制对象比new一个新对象的性能要高得多。
  2. 如果一个对象的实例化过程很耗时耗力,可以使用原型模式。

Java Cloneable接口

Java中提供了一个标记接口Cloneable,类如果实现了这个接口就可以使用Object类中定义的clone方法

如果没有实现Cloneable接口,直接调用clone()会抛出CloneNotSupportedException

Object clone()会返回当前对象的一个浅拷贝

深拷贝和浅拷贝

根据不同的对象类型,拷贝的内容也各不相同:

  1. 基本数据类型,如int,char等,直接拷贝
  2. 对于字符串,拷贝时只复制引用,当字符串的值改变时,会从字符串池中重新生成新的字符串,最终结果和拷贝值一样
  3. 对于对象,拷贝时只复制引用,如果要复制值,需要使用深拷贝
public class Out implements Cloneable{private String outName;private In in;public Out(String outName) {this.outName = outName;}public void setIn(In in) {this.in = in;}@Overridepublic String toString() {return "Out{" +"outName='" + outName + '\'' +", in=" + in +'}';}@Overrideprotected Out clone() throws CloneNotSupportedException {return (Out) super.clone();}public static void main(String[] args) {Out out = new Out("out");In in = new In("in name");out.setIn(in);Out out1 = null;try {// in 是一个object类型,所以在调用clone()时只复制了in的引用out1 = out.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}assert out1 != null;// 改变out1.in的name也会改变out中in的nameout1.in.setName("out1 in");System.out.println(out);System.out.println(out1);}
}
/*
Out{outName='out', in=In{name='out1 in'}}
Out{outName='out', in=In{name='out1 in'}}
*/

深拷贝 DeepCopy

Java中实现深拷贝可以手动拷贝object类型的属性,但如果这个类型中还有object类型,就会很麻烦。

@Override
protected DCOut clone() throws CloneNotSupportedException {DCOut copy = (DCOut) super.clone();In copyIn = (In) this.in.clone();copy.setIn(copyIn);return copy;
}

还可以使用Serializable接口,通过序列化,将堆中的对象数据信息复制一份到堆外,再反序列化成新的克隆对象

import java.io.*;public class DeepClone implements Serializable {private Object obj;public DeepClone(Object obj){this.obj = obj;}public Object deepClone() {Object result = null;//序列化ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = null;try {oos = new ObjectOutputStream(baos);oos.writeObject(obj);} catch (IOException e) {e.printStackTrace();}// 反序列化ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream  ois = null;try {ois = new ObjectInputStream(bais);result = ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return result;}
}

python中的深拷贝和浅拷贝

In [1]: import copyIn [2]: a = [i for i in range(10)]In [3]: b = copy.copy(a)In [4]: a is b
Out[4]: FalseIn [5]: c = [[1, 2], [3, 4]]In [6]: d = copy.copy(c)In [7]: d is c
Out[7]: FalseIn [8]: d[0] is c[0]
Out[8]: TrueIn [9]: e = copy.deepcopy(c)In [10]: e[0] is c[0]
Out[10]: FalseIn [11]:

python内置的copy模块提供了深拷贝和浅拷贝的功能,python中浅拷贝只会拷贝父对象,不会拷贝父对象内部的子对象

python切片属于浅拷贝

《大话设计模式》里简历的例子

package pers.junebao.prototype_pattern;import pers.junebao.prototype_pattern.deep_copy.DeepClone;import java.io.Serializable;public class Resume implements Cloneable, Serializable {private String name;private String education;private String sex;Resume(String name) {this.name = name;}public void setName(String name) {this.name = name;}public void setEducation(String education) {this.education = education;}public void setSex(String sex) {this.sex = sex;}public void print(){System.out.println("name: " + this.name);System.out.println("sex : " + this.sex);System.out.println("education: " + this.education);}@Overridepublic Resume clone() {Resume resume = null;// 深拷贝resume = (Resume) DeepClone.deepClone(this);return resume;}
}
package pers.junebao.prototype_pattern;public class Main {public static void main(String[] args) {Resume resume = new Resume("JuneBao");resume.setSex("男");resume.setEducation("本科");Resume resume1 = resume.clone();resume1.setSex("女");resume.print();resume1.print();}
}

GitHub | 完整代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2016OSC源创会年终盛典-综合技术专场-张小刚

2019独角兽企业重金招聘Python工程师标准>>> 综合技术专场 讲师/SPEAKERS 张小刚 网易云负载均衡项目负责人 《网易蜂巢负载均衡技术实践》从网易蜂巢中的实践出发,分享网易蜂巢负载均衡服务从无到有,从私有云到公有云过程中的技术实践。重点…

python策略模式包含角色_详解Python设计模式之策略模式

虽然设计模式与语言无关,但这并不意味着每一个模式都能在每一门语言中使用。《设计模式:可复用面向对象软件的基础》一书中有 23 个模式,其中有 16 个在动态语言中“不见了,或者简化了”。1、策略模式概述策略模式:定义…

mysql 日期

数据类型 数据类型格式date YYYY-MM-DD datetime YYYY-MM-DD HH:MM:SS timestamp YYYY-MM-DD HH:MM:SS year YYYY 或 YY 具体实现的函数 1、now() 返回当前的日期和时间 SELECT NOW(); 2、curdate() 返回当前的日期 SELECT CURdate(); 3、curtime()返回当…

【Go】panic: reflect: call of reflect.Value.FieldByName on ptr Value

产生原因 调用 FieldByName()方法时,调用者与预期类型不相符。 // 错误代码 func setNewArticleInfoToCache(article *Article) {fields : []string{"Title", "Abstract", "ID", "AuthorID", "CreateTime",}im…

超完整的 Chrome 浏览器客户端调试大全

2019独角兽企业重金招聘Python工程师标准>>> 引言 “工欲善其事,必先利其器” 没错,这句话个人觉得说的特别有道理,举个例子来说吧,厉害的化妆师都有一套非常专业的刷子,散粉刷负责定妆,眼影刷负…

PHP 获取服务器详细信息【转】

碰到此问题,做下记录 获取系统类型及版本号: php_uname() (例:Windows NT COMPUTER 5.1 build 2600)只获取系统类型: php_uname(s) (或&#xff1…

HIVE攻略 JFK_Hive安装及使用攻略

目录Hive的安装Hive的基本使用:CRUDHive交互式模式数据导入数据导出Hive查询HiveQLHive视图Hive分区表1. Hive的安装系统环境装好hadoop的环境后,我们可以把Hive装在namenode机器上(c1)。hadoop的环境,请参考:让Hadoop跑在云端系列文章&#…

MySQL 为什么用索引,为什么是 B+树,怎么用索引

MySQL 索引 A database index is a data structure that improves the speed of operations in a table. Indexes can be created using one or more columns, providing the basis for both rapid random lookups and efficient ordering of access to records. 为什么需要索…

页面加载完毕执行多个JS函数

通常我们需要在打开页面时加载脚本,这些脚本必须在页面加载完毕后才可以执行,因为这时候DOM才完整,可以利用window.onload确保这一点,如:window.οnlοadfirstFunction;这脚本的意思是在页面完毕后执行firstFunction函…

Servlet 生命周期、工作原理

Servlet 生命周期:Servlet 加载--->实例化--->服务--->销毁。init():在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器&…

【Go 并发控制】上下文 context 源码

Context 在 Go 服务中,往往由一个独立的 goroutine 去处理一次请求,但在这个 goroutine 中,可能会开启别的 goroutine 去执行一些具体的事务,如数据库,RPC 等,同时,这一组 goroutine 可能还需要…

js设置全局变量ajax中赋值

js设置全局变量,在ajax中给予赋值赋值不上问题解决方案 方案一、 //在全局或某个需要的函数内设置Ajax异步为false,也就是同步. $.ajaxSetup({async : false}); //然后再进行你的Ajax操作 $.post(地址, 参数, function(data, status) { if (status &q…

iOS开发UI篇—模仿ipad版QQ空间登录界面

一、实现和步骤 1.一般ipad项目在命名的时候可以加一个HD,标明为高清版 2.设置项目的文件结构,分为home和login两个部分 3.登陆界面的设置 (1)设置第一个控制器和自定义的控制器类(登陆)关联 (2&#xff09…

click传值vue_对vue下点击事件传参和不传参的区别详解

如下所示:{{btn_text1}}{{btn_text2}}var _vm new Vue({data : {btn_text1 : 点击1 ,btn_text2 : 点击2},methods : {test_click1 : function (e) {console.log(test_click1--------------------------) ;console.log(e) ;// 输出结果:MouseEvent {isTr…

【Golang 源码】sync.Map 源码详解

sync.Map 不安全的 map go 中原生的 map 不是并发安全的&#xff0c;多个 goroutine 并发地去操作一个 map 会抛出一个 panic package main import "fmt" func main() {m : map[string]int {"1": 1, "2": 2,}// 并发写for i : 0; i < 100;…

oracle中scn(系统改变号)

系统scn&#xff1a; select checkpoint_change# from v$database; 文件scn&#xff1a; select name,checkpoint_change# from v$datafile; 结束scn&#xff1a; select name,last_change# from v$datafile; 数据文件头部scn…

sicktim571操作手册_SICK激光传感器TIM310操作说明书

SICK激光传感器TIM310操作说明书最近更新时间&#xff1a;2015/1/23 13:31:29提 供 商&#xff1a;资料大小&#xff1a;1.2MB文件类型&#xff1a;PDF 文件下载次数&#xff1a;709次资料类型&#xff1a;浏览次数&#xff1a;5192次相关产品&#xff1a;详细介绍&#xff1a;…

Tengine 安装配置全过程

在先前的文章中介绍过Tengine&#xff0c;先前只是使用了运维人员配置好的内容&#xff0c;未自己进行过安装配置。周末闲来无事&#xff0c;对于Tengine进行了尝试性的安装。记录下面方便以后再做改进。Tengine官网上有个非常简单的教程&#xff0c;中间并未涉及到一些常用的设…

【Go】sync.WaitGroup 源码分析

WaitGroup sync.WaitGroup 用于等待一组 goroutine 返回&#xff0c;如&#xff1a; var wg sync.WaitGroup{}func do() {time.Sleep(time.Second)fmt.Println("done")wg.Done() }func main() {go do()go do()wg.Add(2)wg.Wait()fmt.Println("main done"…

什么是响应式设计?为什么要做响应式设计?响应式设计的基本原理是什么?...

页面的设计和开发应当根据用户行为以及设备环境&#xff08;系统平台、屏幕尺寸、屏幕定向等&#xff09;进行相应的响应和调整。具体的实践方式由多方面组成&#xff0c;包括弹性网格和布局、图片、css media query的使用等。无论用户正在使用笔记本还是iPad&#xff0c;我们的…