所谓的原型模式,就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1.首先需要了解java的clone技术
我理解的很简单,无非是把一个对象进行复制粘贴。那么,来看一下JAVA语言中是如何来实现的这个步骤的。我们依次需要知道以下这些事。
1.Object对象中有一个clone()方法。而且是protected。
2.继承于Object的类一般都可以实现这个方法(有特殊的,比如StringBuffer等,官方定的,不去研究它)。
3.想被clone的对象需要实现接口Cloneable。如果此对象的类不能实现接口Cloneable,则会抛出CloneNotSupportedExcetion。
4.所有的数组都被视为实现接口Cloneable。
5.clone分为浅clone(又称影子clone)和深clone。
6.Object类本身不实现接口Cloneable,所以在类为Object的对象上调用clone方法,将会导致在运行时抛出异常。
关键所在深克隆和浅克隆,那到底他们之间有什么区别呢?
首先看一下例子:
public abstract class CloneClass implements Cloneable {
public int aInt;
public Object clone() {
CloneClass o = null;
try {
o = (CloneClass) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return o;
}
}
public class UnCloneA {
private int i;
public UnCloneA(int ii) {
i = ii;
}
public void doublevalue() {
i *= 2;
}
public String toString() {
return Integer.toString(i);
}
}
public class CloneB implements Cloneable {
public int aInt;
public UnCloneA unCloneA = new UnCloneA(111);
public Object clone() {
CloneB o = null;
try {
o = (CloneB) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return o;
}
}
public class Test {
public static void main(String args[]) {
CloneB b1 = new CloneB();
b1.aInt = 11;
System.out.println("before clone,b1.aInt = " + b1.aInt);
System.out.println("before clone,b1.unCA = " + b1.unCloneA);
CloneB b2 = (CloneB) b1.clone();
b2.aInt = 22;
b2.unCloneA.doublevalue();
System.out.println("=================================");
System.out.println("after clone,b1.aInt = " + b1.aInt);
System.out.println("after clone,b1.unCA = " + b1.unCloneA);
System.out.println("=================================");
System.out.println("after clone,b2.aInt = " + b2.aInt);
System.out.println("after clone,b2.unCA = " + b2.unCloneA);
}
}
输出结果:
before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 222
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222
可见,当执行clone这个动作的时候,系统首先开辟一个和它一样的空间。然后分别对其内容进行复制。复制过程中,如果是基本类型,没什么说的,直接把值复制过来。如果不是基本类型,复制的则是该类型对象的引用。
这样的clone就是所谓的浅clone。那很显然,如果上面复制的过程中,对于非基本类型实现的不是一个引用复制,而是创建一个新的一样的对象(其实也是一个clone步骤),那么就是所谓的深clone。对于深度克隆只不过是clone的一种扩展,还有N深clone等等。对于这些,和我们要研究的原型模式没有多少关系。
1、浅克隆:
a. 提供一个类作为克隆的原型,该类实现了Clonable接口
b. 在该类中覆盖Object类的clone()方法,采用super.clone()方法完成克隆
c. 在外部使用场合先产生一个原型对象,然后调用其clone()方法产生克隆对象
2、深克隆:
a. 提供一个类作为克隆的原型,该类实现了Serializable接口
b. 在该类中覆盖Object类的clone()方法,采用序列化的方法完成克隆(对象流的读写)
c.在外部使用场合先产生一个原型对象,然后调用其clone()方法产生克隆对象
二、Prototype模式与深、浅克隆:
使用Object.clone()方法进行的克隆是“浅克隆”-被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。浅克隆的步骤如下:
①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。
②在派生类中覆盖基类的clone()方法,并声明为public。
③在派生类的clone()方法中,调用super.clone()。
④在派生类中实现Cloneable接口。
为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()要识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
要实现“深克隆”-被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
深克隆需要使用Java中提供的对象串行化功能-即把要复制的对象写入到一个缓冲流,然后通过输入流读入,完成对象的复制
下面是深克隆与浅克隆的代码
public class SuperStar implements Cloneable, Serializable {
public String name;
public int height;
public Skill mySkill;
public Object clone() {
Object o = null;
try {
o = super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return o;
}
public Object deepClone() throws Exception {
Object o = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); // (ByteArrayOutputStream)此类实现了一个输出流,其中
// 的数据被写入一个字节数组。缓冲区会随着数据的不断写入而自动增长。
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this); // 通过Serialization机制将自身写入该缓冲区
// 找到刚才开辟的缓冲区准备读取
ByteArrayInputStream bis = new ByteArrayInputStream(bos
.toByteArray()); //
ObjectInputStream ois = new ObjectInputStream(bis);
// 将刚才写入的内容读入一个新的对象
o = ois.readObject();
bos.close();
oos.close();
bis.close();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
public class Skill implements Serializable{
public int strength;
public int jumping;
}
public class Test {
public static void main(String args[]) throws Exception{
SuperStar s1=new SuperStar();
s1.name="姚明";
s1.height=226;
s1.mySkill=new Skill();
s1.mySkill.jumping=50;
s1.mySkill.strength=20;
System.out.println(s1.name+" " + s1.height +" "+s1.mySkill.jumping);
SuperStar s2=(SuperStar) s1.clone();
// SuperStar s2=(SuperStar) s1.deepClone();
s2.name="潘长江";
s2.height=100;
s2.mySkill.jumping=10;
s2.mySkill.strength=5;
System.out.println(s2.name+" " + s2.height+" " +s2.mySkill.jumping);
System.out.println(s1.name+" " + s1.height +" "+s1.mySkill.jumping);
}
}
浅克隆 结果
姚明 226 50
潘长江 100 10
姚明 226 10
深克隆 结果
姚明 226 50
潘长江 100 10
姚明 226 50
JAVA中的clone方法,其实现是native的。这也就意味着它的执行效率是远高于new一个新对象的。所以,当需要生成大量相似对象的时候,可以考虑下应用clone,也就是原形模式。
分享到:
相关推荐
内容概要:本文详细介绍了使用COMSOL多物理场仿真软件,在热流固耦合框架下,研究二氧化碳驱替甲烷过程中的煤层变形、孔渗变化及其对甲烷产量和二氧化碳封存量的影响。首先,文章解释了二氧化碳驱替甲烷作为一种关键技术的意义,然后逐步展示了模型的构建方法,包括设定煤层作为多孔介质、考虑其复杂物理特性(如渗透率、孔隙度)以及模拟二氧化碳注入和甲烷释放过程。接着,通过对模拟结果的分析,揭示了煤层在二氧化碳注入后的明显变形、孔渗特性的显著变化,最终得出甲烷产量与煤层孔渗特性紧密相关,而二氧化碳封存量受煤层变形和孔渗变化影响的结论。最后,强调了该模型对未来理解和优化驱替过程的重要性。 适合人群:从事能源领域研究的专业人士,尤其是关注二氧化碳驱替甲烷技术的研究人员和技术人员。 使用场景及目标:适用于需要深入了解二氧化碳驱替甲烷过程中煤层变形和孔渗变化机理的研究项目,旨在提高甲烷产量和二氧化碳封存量的理解和优化。 其他说明:文中提供了详细的建模步骤和代码分析,有助于读者掌握COMSOL多物理场仿真的具体操作方法。
少儿编程scratch项目源代码文件案例素材-我的世界 守卫者.zip
内容概要:本文详细探讨了制造业工厂中两条交叉轨道(红色和紫色)上的自动导引车(AGV)调度问题。系统包含2辆红色轨道AGV和1辆紫色轨道AGV,它们需完成100个运输任务。文章首先介绍了AGV系统的背景和目标,即最小化所有任务的完成时间,同时考虑轨道方向性、冲突避免、安全间隔等约束条件。随后,文章展示了Python代码实现,涵盖了轨道网络建模、AGV初始化、任务调度核心逻辑、电池管理和模拟运行等多个方面。为了优化调度效果,文中还提出了冲突避免机制增强、精确轨道建模、充电策略优化以及综合调度算法等改进措施。最后,文章通过可视化与结果分析,进一步验证了调度系统的有效性和可行性。 适合人群:具备一定编程基础和对自动化物流系统感兴趣的工程师、研究人员及学生。 使用场景及目标:①适用于制造业工厂中多AGV调度系统的开发与优化;②帮助理解和实现复杂的AGV调度算法,提高任务完成效率和系统可靠性;③通过代码实例学习如何构建和优化AGV调度模型,掌握冲突避免、路径规划和电池管理等关键技术。 其他说明:此资源不仅提供了详细的代码实现和理论分析,还包括了可视化工具和性能评估方法,使读者能够在实践中更好地理解和应用AGV调度技术。此外,文章还强调了任务特征分析的重要性,并提出了基于任务特征的动态调度策略,以应对高峰时段和卸载站拥堵等情况。
内容概要:本文介绍了一个使用MATLAB编写的基于FDTD(时域有限差分)方法的电磁波在自由空间中传播的仿真系统。该系统采用了ABC(吸收边界条件)和正弦脉冲激励源,并附有详细的代码注释。文中首先介绍了关键参数的选择依据及其重要性,如空间步长(dx)和时间步长(dt),并解释了它们对算法稳定性和精度的影响。接着阐述了电场和磁场的初始化以及Yee网格的布局方式,强调了电场和磁场分量在网格中的交错排列。然后详细讲解了吸收边界的实现方法,指出其简单而有效的特性,并提醒了调整衰减系数时需要注意的问题。最后,描述了正弦脉冲激励源的设计思路,包括脉冲中心时间和宽度的选择,以及如何将高斯包络与正弦振荡相结合以确保频带集中。此外,还展示了时间步进循环的具体步骤,说明了磁场和电场分量的更新顺序及其背后的物理意义。 适合人群:对电磁波传播模拟感兴趣的科研人员、高校学生及工程技术人员,尤其是那些希望深入了解FDTD方法及其具体实现的人群。 使用场景及目标:适用于教学演示、学术研究和技术开发等领域,旨在帮助使用者掌握FDTD方法的基本原理和实际应用,为后续深入研究打下坚实基础。 阅读建议:由于本文涉及较多的专业术语和技术细节,建议读者提前熟悉相关背景知识,如电磁理论、MATLAB编程等。同时,可以通过动手实践代码来加深理解和记忆。
少儿编程scratch项目源代码文件案例素材-小鸡会飞.zip
房地产 -云南农博园项目一组团(河尾村)产业规划构思.pptx
haproxy-2.2.17
少儿编程scratch项目源代码文件案例素材-音乐飞翔.zip
少儿编程scratch项目源代码文件案例素材-信仰.zip
scratch少儿编程逻辑思维游戏源码-锯切片.zip
scratch少儿编程逻辑思维游戏源码-货车.zip
scratch少儿编程逻辑思维游戏源码-火箭动力超级鱿鱼.zip
scratch少儿编程逻辑思维游戏源码-滚动的天空.zip
scratch少儿编程逻辑思维游戏源码-极速求生.zip
scratch少儿编程逻辑思维游戏源码-火柴人战争.zip
内容概要:本文详细介绍了MATLAB一维PCHE微通道换热器模型在能源工质系统中的应用。首先,文章阐述了PCHE的设计与模型建立,强调了进出口节点温度参数对确定PCHE长度和换热量的重要性。接着,文中采用了湍流型长直半圆通道Gnielinki方程来计算流动换热的努塞尔数,从而评估PCHE的换热性能。最后,通过MATLAB调用Refprop物性库求解普朗特数,进一步优化PCHE的设计,提升其换热效率。研究表明,这种模型有助于提高能源工质系统的换热性能,推动微通道换热器在能源领域的广泛应用。 适合人群:从事能源工程、热力学、换热器设计等相关领域的研究人员和技术人员。 使用场景及目标:适用于需要精确计算和优化微通道换热器性能的研究项目,旨在提高能源利用效率并减少环境污染。 其他说明:随着计算机技术的发展,一维PCHE微通道换热器模型将进一步完善,为能源领域的发展提供更强有力的支持。
少儿编程scratch项目源代码文件案例素材-星际飞船.zip
少儿编程scratch项目源代码文件案例素材-外星异形战跑.zip
图25. 火焰成像装置捕获图像示意图
scratch少儿编程逻辑思维游戏源码-僵尸射击.zip