java设计模式---原型模式
原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
通俗来说:原型模式就是深拷贝和浅拷贝的实现。
浅拷贝
只实现了值拷贝,对于引用对象还是指向原来的对象。
- 父类实现clone方法,子类没有实现clone方法,其效果是浅拷贝。
- 父类实现clone方法,子类也实现clone方法,本来我想应该是深拷贝了,没想到也是浅拷贝。
package com.prototype;
import java.io.Serializable;
public class Work implements Serializable,Cloneable{
private static final long serialVersionUID = 207835812839542204L;
private String job;
private double salary;
public Work(String job,double salary) {
this.job = job;
this.salary = salary;
}
@Override
public String toString() {
return "Work [job=" + job + ", salary=" + salary + "]";
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.prototype;
import java.io.Serializable;
public class User implements Serializable,Cloneable{
private static final long serialVersionUID = -2260332138558500447L;
private String name = "";
private Work work = null;
public User(String name,String job,double salary) {
this.name=name;
work = new Work(job, salary);
}
public void changeJob(String job){
this.work.setJob(job);
}
/*只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,
因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB。
重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的。
*/
//浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "User [name=" + name + ", work=" + work + "]";
}
}
package com.prototype;
public class Main {
public static void main(String[] args) {
try {
User user1 = new User("zhangsan","ceo",100000);
User user2 = (User) user1.clone();
System.out.println(user1);
System.out.println(user2);
System.out.println("修改job");
user2.changeJob("cfo");
System.out.println(user1);
System.out.println(user2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
//结果
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
修改job
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
深拷贝
即实现了值拷贝,也实现了对引用对象的拷贝。
- 法一
//深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
//实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
public Object deepClone() throws IOException, ClassNotFoundException{
//写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//读入二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
- 法二
//将User的拷贝方法修改为下面的方法。
@Override
protected Object clone() throws CloneNotSupportedException {
Work w = (Work) work.clone();//对其引用变量进行拷贝
User u = (User)super.clone();//自身拷贝
u.work = w;//引用变量重新赋值。
return u;
}
定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
使用场景
原型模式被用在频繁调用且极其相似的对象上,它会克隆对象并设置改变后的属性,而且消耗的资源较少。
代码举例实现
ProtoTypeImpl.java
package com.design.prototype;
public class ProtoTypeImpl implements Cloneable{
private int shallowClone;
private DeepClone deepClone = new DeepClone();
public ProtoTypeImpl() {
System.out.println("construct is called");
}
public void print() {
// TODO Auto-generated method stub
System.out.println(shallowClone);
System.out.println(deepClone.getS());
}
@Override
protected ProtoTypeImpl clone(){
// TODO Auto-generated method stub
try{
ProtoTypeImpl protoTypeImp = (ProtoTypeImpl) super.clone();
//protoTypeImp.shallowClone = this.shallowClone;
//protoTypeImp.deepClone = this.deepClone.clone();
return protoTypeImp;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
public void setShallowClone(int shallowClone) {
this.shallowClone = shallowClone;
}
public void setS(String s){
deepClone.setS(s);
}
}
DeepClone.java
package com.design.prototype;
public class DeepClone implements Cloneable{
private String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
protected DeepClone clone(){
// TODO Auto-generated method stub
try {
return (DeepClone)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
App.java
package com.design.prototype;
public class App {
public static void main(String[] args) {
// TODO Auto-generated method stub
ProtoTypeImpl protoTypeImp = new ProtoTypeImpl();
protoTypeImp.setShallowClone(1);
protoTypeImp.setS("deep clone");
protoTypeImp.print();
System.out.println("-------------");
ProtoTypeImpl protoTypeImp2 = protoTypeImp.clone();
protoTypeImp2.setShallowClone(2);
protoTypeImp2.setS("deep clone 2");
protoTypeImp2.print();
System.out.println("-------------");
protoTypeImp.print();
}
}
结果分析
这个现象主要是由于深浅复制引起的,普通类型的数据没有问题,而对象类型则有问题。同时我们应该注意到clone的时候构造函数是不会被调用的。
去掉ProtoTypeImpl.clone的两行注释(第一行没什么所谓,但是还是加上,有个对比)
运行结果2.png总结优缺点
- 优点
原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其点。 - 缺点
使用过程中要切记构造函数不会被调用,所以在构造函数完成的操作应该多加处理,还有深浅复制的问题
- 优点
java设计模式---原型模式的更多相关文章
- 【设计模式】Java设计模式 - 原型模式
[设计模式]Java设计模式 - 原型模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...
- 我的Java设计模式-原型模式
"不好意思,我是卧底!哇哈哈哈~"额......自从写了上一篇的观察者模式,就一直沉浸在这个角色当中,无法自拨.昨晚在看<使徒行者2>,有一集说到啊炮仗哥印钞票,我去, ...
- Java设计模式—原型模式
原型设计模式是一种比较简单的设计模式,在项目中使用的场景非常多. 个人理解: 原型模式实现了对Java中某个对象的克隆功能,即该对象的类必须implements实现Cloneable接口来标识为可被克 ...
- Java设计模式-原型模式(Prototype)
原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 原型模式的结构 原型模式要求对象实现一个可以“克 ...
- 4.java设计模式-原型模式(prototype)
在<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更 ...
- Java设计模式原型模式
原型模式: – 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式. – 就是java中的克隆技术,以某个对象为原型,复制出新的对象.显然,新的对象具备原型对象的特点 – 优势 ...
- java设计模式——原型模式
一. 定义与类型 定义:指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.不需要知道任何创建的细节,不调用构造函数 类型:创建型 二.使用场景 类初始化消耗较多资源 new 产生的一个对 ...
- PHP 设计模式 原型模式(Prototype)之深/浅拷贝
看PHP 设计模式 原型模式(Prototype)时,衍生出一个扩展问题之 原型拷贝的浅拷贝和深拷贝问题(不管写Java还是写PHP还是写JS时都多多少少遇到过对象拷贝问题) 比如写前端页面时 ...
- 10. 星际争霸之php设计模式--原型模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
随机推荐
- MSSQL 字符串替换语句
MSSQL替换语句:update 表名 set 字段名=replace(cast(字段名 as varchar(8000)),'abc.com','123.com')例如:update PE_Arti ...
- 如何在苹果官网下载旧版本的Xcode 方法
1 在百度里输入“苹果开发者中心“,进入以下页面.点击页面中的“Member Center" 2 出现登录界面.这是需要苹果开发者帐号的,没有帐号的可以选择“Create Apple ...
- iOS 天气应用代码中文介绍
天气应用 解释请求参数 q: 表示Location(可以给出城市名字;或者直接给城市的经纬度) 例子:q=beijing 例子 q=48.834,2.394 num_of_days: 需要预报的天数 ...
- php在.php文件中设置php.ini,仅对当前文件有效
ini_set (PHP 4, PHP 5, PHP 7) ini_set — 为一个配置选项设置值 折叠返回值 成功时返回旧的值,失败时返回 FALSE. 折叠范例 <?php echo in ...
- QT 5.1.1 for Android 开发环境搭建与配置【Windows 7】
前言:本人操作系统为Windows7 64位,用的是32位的安装包,32位系统没有验证. 一.首先下载以下安装包,如果提供的链接失效请自行下载: (1) Android SDK (Windows 32 ...
- PHP微信红包的算法实现探讨
header("Content-Type: text/html;charset=utf-8");//输出不乱码,你懂的 $total=10;//红包总额 $num=8;// 分成8 ...
- CWnd类
CWnd类的成员 .数据成员 m_hWnd 指明与这个CWnd对象相关联的HWND句柄 .构造和析构 CWnd 构造一个CWnd对象 DestroyWindow 销毁相关联的Windows窗口 .初始 ...
- 最简单的ASP动态页面生成伪静态方法
目前网站制作中很多网站都采用生成静态页的方法,原因是这样访问速度会得到提高(服务器端CPU利用率很低),另外也容易被搜索引擎收录,但是这带来的一个问题就是需要足够大的空间存放这些静态页面,如果你的空间 ...
- C#7.0
C#7.0中有哪些新特性? 以下将是 C# 7.0 中所有计划的语言特性的描述.随着 Visual Studio “15” Preview 4 版本的发布,这些特性中的大部分将活跃起来.现在是时候来展 ...
- IOS开发之免费证书+不越狱真机调试
本文转自:http://www.cnblogs.com/weii/p/4688299.html 苹果发布Xcode7后, 开放了普通的AppleID也能真机调试,非$99 或 $299, 只要能上 ...