创建型模式:原型模式
个人公众号原文: 创建型模式:原型模式
五大创建型模式之五:原型模式。
简介
姓名 :原型模式
英文名 :Prototype Pattern
价值观 :效率第一
个人介绍 :
Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype. 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 (来自《设计模式之禅》)
又到了一个系列的最后一篇文章了,今天是创建型模式的最后一篇。什么是创建型模式呢?创建型模式是对类的实例化过程进行抽象,使对象的创建和使用分离,从而使代码更加灵活。
我们平时使用最多的一种创建对象方式就是 new ABC(),直接通过构造方法来创建一个对象。通过原型模式来创建对象则不用调用构造方法,就可以创建一个对象。下面来揭开它的面纱。
你要的故事
前几天有出版社的老师邀请写书,鉴于深知自己水平还不足以出书,所以没有合作,还在努力学习,以后有能力有机会再考虑这方面的事情。
今天的故事就从出书讲起。我们知道一本新书发版的时候,会复印很多册,如果销售得好,会有很多个印刷版本。我们来了解复印一批书籍这个过程是怎么实现的。小明写下了下面这段代码。
public class NoPrototypeTest { public static void main(String[] args) { for (int i = 1; i <= 10; i ++) { Book book = new Book("娱乐至死", "尼尔波兹曼", "社会科学", "XXXX"); System.out.println("复印书籍:" + book.getName() + ",第 " + i + " 本"); } } } class Book { private String name; private String author; private String type; private String content; public Book(String name, String author, String type, String content) { this.name = name; this.author = author; this.type = type; this.content = content; System.out.println("实例化书籍:" + this.name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } // 打印结果: 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 1 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 2 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 3 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 4 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 5 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 6 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 7 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 8 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 9 本 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 10 本
上面小明的代码复印了 10 本《娱乐至死》,代码逻辑没有问题,有个问题就是复印一本就实例化一次书籍,这个实例化可以减少么?使用原型模式可以实现。小明根据这些提示,重新修改了代码。
public class PrototypeTest { public static void main(String[] args) { Book2 book1 = new ConcreteBook("娱乐至死", "尼尔波兹曼", "社会科学", "XXXX"); System.out.println("复印书籍:" + book1.getName() + ",第 " + 1 + " 本"); for (int i = 2; i <= 10; i ++) { Book2 book2 = (Book2) book1.clone(); System.out.println("复印书籍:" + book2.getName() + ",第 " + i + " 本"); } } } /** * 抽象类 */ abstract class Book2 implements Cloneable { private String name; private String author; private String type; private String content; public Book2(String name, String author, String type, String content) { this.name = name; this.author = author; this.type = type; this.content = content; System.out.println("实例化书籍:" + this.name); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } } /** * 具体类 */ class ConcreteBook extends Book2 { public ConcreteBook(String name, String author, String type, String content) { super(name, author, type, content); } } 打印结果: 实例化书籍:娱乐至死 复印书籍:娱乐至死,第 1 本 复印书籍:娱乐至死,第 2 本 复印书籍:娱乐至死,第 3 本 复印书籍:娱乐至死,第 4 本 复印书籍:娱乐至死,第 5 本 复印书籍:娱乐至死,第 6 本 复印书籍:娱乐至死,第 7 本 复印书籍:娱乐至死,第 8 本 复印书籍:娱乐至死,第 9 本 复印书籍:娱乐至死,第 10 本
看,打印结果和第一次实现的结果完全不一样,这一次只实例化了一次,后面复印的书籍都没有实例化。我们看看代码的变化,代码中最最主要的就是 Book2 实现了 Cloneable 接口,这个接口有个 clone() 方法,通过实现这个方法,可以实现对象的拷贝,就是不用调用构造方法,直接通过对内存的拷贝来创建一个新的对象。这就是原型模式的实现方式,通过原型模式可以提高创建对象的效率。
总结
通过原型模式,绕过构造方法创建对象,利用内存直接拷贝对象,提高对象的创建性效率。在有大量的对象创建或者类初始化消耗多资源的场景下可以利用原型模式来优化。当然在实现的过程中,要注意浅拷贝与深拷贝的问题,防止写出 bug,文章主要介绍原型模式,就不详细说这个问题了,留给大家去扩展了解。
参考资料:《大话设计模式》、《Java设计模式》、《设计模式之禅》、《研磨设计模式》、《Head First 设计模式》
推荐阅读:
希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
[译]PEP 342--增强型生成器:协程
PEP原文 : https://www.python.org/dev/peps/pep-0342/ PEP标题: Coroutines via Enhanced Generators PEP作者: Guido van Rossum, Phillip J. Eby 创建日期: 2005-05-10 合入版本: 2.5 译者 :豌豆花下猫(Python猫 公众号作者) 目录 简介 动机 规格摘要 规格:将值发送到生成器 新的生成器方法:send(value) 新的语法:yield 表达式 规格:异常和清理 新语法:yield 允许在try-finally中 新的生成器方法:throw(type,value = None,traceback = None) 新的标准异常:GeneratorExit 新的生成器方法:close() 新的生成器方法:__del__() 可选的扩展 扩展的 continue 表达式 未决问题 示例 参考实现 致谢 参考文献 版权 简介 这个 PEP 在生成器的 API 和语法方面,提出了一些增强功能,使得它们可以作为简单的协程使用。这基本上是将下述两个 PEP 的...
- 下一篇
再谈HTTP2性能提升之背后原理—HTTP2历史解剖
即使千辛万苦,还是把网站升级到http2了,遇坑如《phpcms v9站http升级到https加http2遇到到坑》。 因为理论相比于 HTTP 1.x ,在同时兼容HTTP/1.1 完全语义,进一步减少了网络延迟。 对于前端开发人员来说,无疑减少了在前端方面的优化工作。比如雪碧图&文件合并||内容内嵌||域名分片 http1.0的缺点 http1.0被抱怨最多的就是连接无法复用,和head of line blocking这两个问题。理解这两个问题有一个十分重要的前提:客户端是依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的server同时建立6~8个连接,手机端的连接数则一般控制在4~6个。显然连接数并不是越多越好,资源开销和整体延迟都会随之增大。 连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。 head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞。假设有5个请求同时发出,对于http1.0的实现,在第一个请求没有收到回复之前,后续从应用层发出的请求只...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 2048小游戏-低调大师作品