小唐说设计模式————原型模式
什么是原型模式
原型模式(Prototype Pattern)是五种创建型模式的其中一种,用原型实例指定创建对象的种类作为原型,并且通过拷贝原型来创建新的对象。
为什么要使用原型模式
新建一个对象有时候会很麻烦,可能涉及大量的变量初始化,函数、代码块的执行,不仅浪费资源,还会涉及数据准备、访问权限等操作。
实现
原型模式至少涉及两个角色:
- Prototype,即原型类:需要实现Cloneable接口,并重写clone()方法,为外部提供一个克隆自身的方法;
- Client,即应用类:让一个原型克隆自身从而创建一个新的对象。
public class Prototype implements Cloneable {//自身的一些方法...@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}
}
public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Prototype prototype1 = (Prototype) prototype.clone();...}
}
为了探讨其中的一些细节,我们对上面的代码稍微添加一些细节部分:
public class Prototype implements Cloneable {private String name;public Prototype() {System.out.println("empty constructor--------------------");}public Prototype(String name) {System.out.println("constructor--------------------");this.name = name;}@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return super.toString() + " " + this.getName();}
}public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();prototype.setName("111");System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}
在Prototype类中加入了构造函数,重写了toString(),运行main(),结果如下:
empty constructor--------------------
com.company.Prototype@4554617c 111
com.company.Prototype@74a14482 111
com.company.Prototype@4554617c 111
com.company.Prototype@74a14482 222
可以看出:
构造函数只执行了一次,说明复制原型类的对象并不需要执行构造函数;
原对象和复制对象的地址不同,说明是重新创建的;
目前看来,在复制完成之后,复制的对象似乎和原对象就没有关系了,原对象的改变不会影响复制的对象,复制的对象改变也不会影响原对象。
真的是这样吗?
我们修改一下代码:
public class Car {private String color;public Car() {}public Car(String color) {this.color = color;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}
}public class Prototype implements Cloneable {private String name;private Car car;public Prototype() {System.out.println("empty constructor--------------------");}public Prototype(String name) {System.out.println("constructor--------------------");this.name = name;}public Prototype(String name, Car car) {this.name = name;this.car = car;}@Overridepublic Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();return proto;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return super.toString() + " " + this.getName() + " " + this.getCar().getColor() + " Car" + " " + this.getCar().toString();}
}public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Car car1 = new Car("red");Car car2 = new Car("yel");prototype.setName("111");prototype.setCar(car1);System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");prototype1.setCar(car2);System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}
执行结果:
empty constructor--------------------
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 111 red Car com.company.Car@74a14482
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 222 yel Car com.company.Car@677327b6
可以看过结果中第4行和第5行,Car的颜色和地址都不一样,我几乎可以得出结论它们确实不是一个对象了,但是这样写其实是有漏洞的,我通过setCar()是显式地改变了这个对象,不能正确得出结论。
再将输出改一下:
public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype prototype = new Prototype();Car car1 = new Car("red");prototype.setName("111");prototype.setCar(car1);System.out.println(prototype.toString());Prototype prototype1 = (Prototype) prototype.clone();System.out.println(prototype1.toString());prototype1.setName("222");prototype1.getCar().setColor("black");System.out.println(prototype.toString());System.out.println(prototype1.toString());}
}
结果变为:
empty constructor--------------------
com.company.Prototype@4554617c 111 red Car com.company.Car@74a14482
com.company.Prototype@1540e19d 111 red Car com.company.Car@74a14482
com.company.Prototype@4554617c 111 black Car com.company.Car@74a14482
com.company.Prototype@1540e19d 222 black Car com.company.Car@74a14482
所有的Car对象的地址都是同一个,颜色值也一同改变,说明clone()实现的是浅拷贝。
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型仍指向的还是原对象所指向的地址。 深复制:将一个对象复制后,基本数据类型和引用类型都重新创建。
如果想对引用类型也实现深拷贝,可以采用二进制流读写等操作实现,此处不再详述。
小唐说设计模式————原型模式相关推荐
- 小唐说设计模式————策略模式篇
策略模式适用于什么样子的场景呢? 当我们的代码中出现了一连串的if-else-或者是switch-case-语句时,我们的代码体就会很长很臃肿,阅读性大大下降,此时可采用策略模式进行重构. 原 ...
- 设计模式 原型模式_创新设计模式:原型模式
设计模式 原型模式 原型模式用于创建对象的副本. 这种模式非常有用,特别是当从头开始创建对象的成本很高时. 与builder , factory和abstract factory模式相比,它不会从头开 ...
- 设计模式 原型模式_设计模式:原型
设计模式 原型模式 创新设计模式之一是原型设计模式 . 尽管原型是创造模式,但它在概念上与其他模式有所区别. 我的意思是原型在某种意义上创造了自己. 我将在下面解释. 原型模式的所有魔力都基于Java ...
- 设计模式 原型模式_原型设计模式:创建另一个小车
设计模式 原型模式 创建对象确实是一个耗时的过程,也是一件昂贵的事情. 因此,我们现在正冒险节省时间和金钱. 我们该怎么做? 克隆奇迹多莉 有人记得多莉吗? 是的,是绵羊,是第一个被克隆的哺乳动物. ...
- Java常用设计模式————原型模式(一)
介绍 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式用于创建重复的对象,同时又能保证性能.当直接创建对象的代价比较大时,则采用 ...
- 第六章 Caché 设计模式 原型模式
文章目录 第六章 Caché 设计模式 原型模式 定义 使用场景 优点 结构图 描述 示例 初级写法 缺点 中级写法 缺点 高级写法 (浅复制) 浅复制 深复制 完整示例 简历类(复制类) 对象类(工 ...
- C++设计模式——原型模式(Prototype Pattern)
C++设计模式--原型模式(Prototype Pattern) 微信公众号:幼儿园的学霸 目录 文章目录 C++设计模式--原型模式(Prototype Pattern) 目录 定义 代码示例 普通 ...
- Python设计模式——原型模式
原型模式(Protoype) 也可以称为复制模式.用原型模式,本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,这既隐藏了对象创建的细节,又能大大降低耗时,提高性能. 目的: 原型模式用 ...
- Java设计模式——原型模式
概述 原型模式是为了解决一些不必要的对象创建过程.当Java JDK中提供了Cloneable接口之后,原型模式就变得异常的简单了.虽然由于Cloneable的引入使用程序变得更简单了,不过还是有一些 ...
最新文章
- 论坛报名 | 与联合国、世卫组织等专家共话人工智能伦理与可持续发展
- 《研磨设计模式》chap12 观察者模式observer(2)模式介绍
- 02_pandas获取数据(指定列获取、[]方式获取、loc函数,at函数, iloc函数 iat函数)
- 年后来广州第一天,写篇水文
- jmeter对乱码如何处理_JMeter读取 Excel 表中用例数据实现接口压测
- 分布式事物框架TCC-Transaction使用教程
- Vue学习笔记(三) —— 前后端交互
- JAVA简单的SWING及AWT
- 用winformz时间格式不正确_巨峰葡萄不能膨大?错!在正确的时间,用对方法,收获优质果穗型...
- zb_system login.php,zblog后台登录地址怎么修改?
- 使用python构建基于hadoop的mapreduce日志分析平台
- 分析 2017年淘宝天猫活动时间安排
- 使用Hooks实现防抖节流 TS版本
- Idea如何设置类头注释(图片步骤直接到位)
- 安装webase时报错,Nginx冲突!
- keepalived结合nginx主备高可用实现
- 全球时区(查询备用)
- asc速度慢 mysql_按desc排序的mysql速度很快,但asc速度很慢
- 记一次网络风暴/网络环路
- Qmsg酱实现QQ消息自由推送