什么是 “原型模式” ?

作者:东风玖哥,小灰

来源:程序员小灰


—————  第二天  —————


————————————


假如有一天,小灰被外星人抓走了,外星人要拿小灰做实验,想了解小灰在吃得好、睡得好、玩得开心的场景下,与现实中小灰的生存状态有什么区别。

于是,外星人克隆了几个一模一样的小灰:

就这样,小灰的原型被留在现实中,而三个复制体分别提供了吃得好、睡得好、玩得开心三种不同环境,小灰的原型则不受三个复制体的影响。

过了一段时间,我们来观察一下本体与分身的生存状态:

在Java语言中,Object类实现了Cloneable接口,一个对象可以通过调用Clone()方法生成对象,这就是原型模式的典型应用。但需要注意的是,clone()方法并不是Cloneable接口里的,而是Object类里的,Cloneable是一个标识接口,标识这个类的对象是可被拷贝的,如果没有实现Cloneable接口,却调用了clone()方法,就会报错。

// protected native Object clone() throwsCloneNotSupportedException;protected Object clone() throws
CloneNotSupportedException {if (!(this instanceof Cloneable)) {throw new CloneNotSupportedException(
"Class " + getClass().getName() +
" doesn't implement Cloneable");}return internalClone();
}// Native helper method for cloning.private native Object internalClone();

 

 

Java中的数据类型,分为基本类型和引用类型。在一个方法里的变量如果是基本类型的话,变量就直接存储在这个方法的栈帧里,例如int、long等;而引用类型则在栈帧里存储这个变量的指针,指向堆中该实体的地址,例如String、Array等。深拷贝和浅拷贝是只针对引用数据类型的。

 

比如一个方法有一个基本类型参数和一个引用类型参数,在方法体里对参数重新赋值,会影响传入的引用类型参数,而不会影响基本类型参数,因为基本类型参数是值传递,而引用类型参数是引用传递。

先定义一个用户类:

// 这是一个非常简单的用户类public class User {private String name;private int age;public User(String name, int age) {this.name=name;this.age=age;}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;}@Overridepublic String toString() {return "User{name='" + name + ", age=" + age +'}';}}
private int x=10;public void updateValue(int value){value = 3 * value;
}private User user= new User("大黄",20);public void updateUser(User student){student.setName("小灰");student.setAge(18);
}public void test(){System.out.println("调用前x的值:"+x);updateValue(x);System.out.println("调用后x的值:"+x);System.out.println("调用前user的值:"+user.toString());updateUser(user);System.out.println("调用后user的值:"+user.toString());}

测试:

Log打印结果如下:

调用前x的值:10
调用后x的值:10
调用前user的值:User{name='大黄, age=20}
调用后user的值:User{name='小灰, age=18}

传递基本类型的方法(updateValue())流程图: 

传递引用类型的方法(updateUser())流程图:

这其中也包含着例外,比如String类型和大小不超过127的Long类型,虽然也是引用类型,却像基本类型一样不受影响。这是因为它们会先比较常量池维护的值,这涉及VM的内容,今天不做过多讨论。

浅拷贝是在按位(bit)拷贝对象,这个对象有着原始对象属性值的一份精确拷贝。我们结合应用场景分析一下,还是刚才的User类,我们增加一个存放地址的内部类Address,我们需要用户信息可以被其他module查询,但是不允许它们被其他module修改,新增代码如下:

// 这是一个稍微复杂的、支持拷贝的用户类public class User implements Cloneable {
// ……省略上文代码……private Address address;@NonNull@NotNull@Overridepublic User clone() {try{return (User)super.clone();}catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}public class Address{// 地市public String city;// 区县public String county;// 乡镇街道public String street;} 
}

 

// 这是一个更复杂的、支持深拷贝的用户类public class User implements Cloneable {// ……省略上文代码……@NonNull@NotNull@Overridepublic User clone() {try{User newUser = (User)super.clone();newUser.setName(this.name);newUser.setAddress(this.address.clone());return newUser;}catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}public class Address implements Cloneable{// ……省略上文代码……@NonNull@NotNull@Overridepublic Address clone() {try{Address newAddress = (Address)super.clone();newAddress.city = this.city;newAddress.county = this.county;newAddress.street = this.street;return newAddress;}catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}}
}

需要注意的是,上面代码的深拷贝其实并不彻底,因为彻底的深拷贝几乎是不可能实现的,那样不但可能存在引用关系非常复杂的情况,也可能存在引用链的某一级上引用了一个没有实现Cloneable接口的第三方对象的情况。

绝大多数设计模式都是牺牲性能提升开发效率的,原型模式则是为数不多的牺牲开发效率提升性能的设计模式。

 

private User user= new User("大黄",20);public void testNew(){User user1 = new User("小灰",18);}public void testClone(){User user2 = user.clone();}

通过ASM工具查看bytecode,可以看出二者对栈资源的消耗: 

// access flags 0x1public  testNew()V……省略……MAXSTACK  = 4MAXLOCALS = 2// access  flags 0x1public  testClone()V……省略……MAXSTACK  = 1MAXLOCALS = 2
}


@Overridepublic Object clone() {return new Intent(this);}


最后我们来总结一下原型模式的核心用途:

1.解决构建复杂对象的资源消耗问题,提升创建对象的效率。

2.保护性拷贝,防止外部对只读对象进行需修改。



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

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

相关文章

制造业全链数字化业务转型实践

近日,阿里云Lindorm与Intel、OSIsoft推出了面向工业物联网信息经济(Infonomics)的IT & OT超融合工业数据云解决方案。方案通过云端打通阿里云、Intel的IT技术积累和OSIsoft的OT经验能力,实现对传统技术供需关系的超越&#xf…

从搜索引擎到核心交易数据库,详解阿里云神龙如何支撑双11

简介: 订单峰值58.3万笔/秒,销售额4982亿,阿里云神龙再次成功扛住了全球流量洪峰 2020年的双11,天猫又创造了新的纪录:订单峰值达到创纪录的58.3万笔/秒,销售额达到历史新高4982亿,阿里云神龙再…

云网一体,“湘遇湘融 | 移动云TeaTalk·长沙站 启动倒计时

在企业数字化转型、云服务和国家政策等多重因素驱动下,越来越多的企业、行业和政府机关将业务迁移到云上,单一化的网络连接模式已经不能满足企业“多系统、多场景、多业务”的上云需求,而是要求云和多样化网能力高度协同。中国移动作为运营商…

matlab save txt 乱码,matlab代码或中文复制到word就变成乱码怎么办?

在matlab的edit中编辑的脚本程序复制到word时,注释里面的汉字变为乱码怎么办。下面教你两种解决办法。软件名称:Matlab 7.0.1 R14 SP1 (3CD带序列号)免费版软件大小:1.17GB更新时间:2012-11-03立即下载1、这是我在matlab的edit下面…

EMAS 移动 DevOps 解决方案 —— Mobile DevOps

简介: DevOps这一优秀的软件交付理念在服务端已经有很多相关的实践,那么是否也可以应用到移动端进行交付呢?基于移动端和服务端场景的差异,移动DevOps跟服务端DevOps又有哪些不同和挑战?本文分享阿里云云原生应用研发平…

MongoDB 5.0 来了,原生时序、版本化 API 新特性悉数登场

作者 | 伍杏玲出品 | CSDN云计算(ID:CSDNcloud)据 DB-Engines 数据库最新 7 月流行度排行榜显示,前五名十分稳定:Oracle、MySQL、Microsoft SQL Server、PostgreSQL、MongoDB,其中 MongoDB 是唯一的文档型数…

阿里云Lindorm与Intel、OSIsoft共建IT OT超融合工业数据云

近日,阿里云Lindorm与Intel、OSIsoft推出了面向工业物联网信息经济(Infonomics)的IT & OT超融合工业数据云解决方案。方案通过云端打通阿里云、Intel的IT技术积累和OSIsoft的OT经验能力,实现对传统技术供需关系的超越&#xf…

wamp php5.6 mysql5.6,WampServer 3.0.6 多语言版 集成apache2.4.23 mysql5.7.14 php5.6.25-7.0.10 穿墙书店...

WampServer是一款由法国人开发的Apache Web服务器、PHP解释器以及MySQL数据库的整合软件包,就是Windows Apache Mysql PHP集成安装环境,即在window下的apache、php和mysql的服务器软件。免去了开发人员将时间花费在繁琐的配置环境过程,从而腾出更多精力去…

阿里云数据中台助力零售耐消品新客获取与转化

天猫消电家装联合安永战略咨询基于阿里巴巴品牌数据银行AIPL的资产积累与流转情况,设计了数字化新客运营指标体系NEW。 这一体系以消费者资产作为品牌方经营的运营基石,基于消费者人群的评估、监测、驱动来带动品牌当下及未来商业的增长。关于NEW这一指…

字节大数据手册火了 ! 离线数据/实时数据/数据仓库ETL/实时交易系统/啥都有 !...

最近有幸在一位字节跳动大数据高级工程师手里扒到了这份学习笔记,将部分知识章节发布到了在B站上竟然获得了5000点赞!本来想将文件上传到github上,但由于文件太大有的都无法显示所以直接整理成多个文件夹,供大家学习,也…

专访阿里云 Serverless 负责人:无服务器不会让后端失业

2012 年,云基础设施服务提供商 Iron.io 的副总裁 Ken 谈到软件开发行业的未来,首次提出了 Serverless 的概念,为云中运行的应用程序描述了一种全新的系统体系架构。此后,以 AWS 为代表的云服务厂商将 Serverless 概念逐步落地&…

php模糊搜索慢怎么办,MySQL中文模糊检索问题的解决方法_php

mysql中文模糊检索问题的解决方法来源:林兴陆在 MySQL 下,在进行中文模糊检索时,经常会返回一些与之不相关的记录,如查找 "-0x1.ebea4bfbffaacp-4%" 时,返回的可能有中文字符,却没有 a 字符存在。…

消息队列RocketMQ性能测试案例

1. 消息队列RocketMQ性能测试案例 1.1 RocketMQ测试分析 客户场景,信息共享交换平台: 1.交换平台需支持每秒万级别数据传输 2.实现跨路段、跨部门、跨行业、跨区域信息即时共享,做到高可靠、低延迟 客户现场展示场景设计思路: 1…

揭秘百度微服务监控:百度游戏服务监控的演进

导读:臣闻防患于未然者易,除患于已然者难 —— 明马文升《添风宪以抚流民疏》作为一个程序员,是否有留意到每逢节假日在各大景区时有程序员打开电脑紧急处理线上问题?如果线上出现大量的报警,这时我们该如何判断是自身…

「更高更快更稳」,看阿里巴巴如何修炼容器服务「内外功」

作者 | 守辰、志敏来源|阿里巴巴云原生公众号 11 月 11 日零点刚过 26 秒,阿里云再一次抗住了全球最大的流量洪峰。今年 双11 是阿里经济体核心系统全面云原生化的一年,相比去年核心系统的上云,云原生化不仅让阿里享受到了云计算技术成本优化…

云原生应用架构转型不好做?阿里云这个平台让你一步到位!

云原生实践带来的挑战 阿里云云原生为企业提供了完善的容器服务、函数计算、微服务体系、中间件体系。每个服务都有伸缩性、弹性和组合性,通过产品选择或组合搭建,能轻松完成应用与运行环境解耦,和传统应用研发模式具有较大差异。从传统研发…

对话MathWorks:解读MATLAB技术生态圈与未来趋势

37年前的1984年,MathWorks公司在美国加州成立。在成立的第14个年头,销售额就达到了一个亿美金。如今MathWorks公司在全球有超过5000名员工分布在34个办公室,2020年的销售额已达12亿美金。众所周知,MathWorks手握MATLAB和Simulink两…

如何基于DataWorks构建数据中台?

一 新零售的商业模式 一家新零售企业如果要做数据中台的话,首先很重要的一点就是一定要懂业务。之前有位同学问过我,说数据中台很难建。在我看来,数据跟业务是息息相关的,在构建整个数据中台的时候,首先要对业务有一个…

浪潮云海OS再度登顶 SPEC Cloud性能得分「全球第一」

近日,国际标准性能评测组织SPEC(Standard Performance Evaluation Corporation)公布最新云计算性能 Cloud IaaS 2018 Benchmark 测试成绩,在同规模测试场景下,浪潮云海OS再次刷新世界纪录,性能得分全球第一…

降本增效利器!趣头条Spark Remote Shuffle Service最佳实践

王振华,趣头条大数据总监,趣头条大数据负责人曹佳清,趣头条大数据离线团队高级研发工程师,曾就职于饿了么大数据INF团队负责存储层和计算层组件研发,目前负责趣头条大数据计算层组件Spark的建设范振,花名辰…