Java 设计模式以虹猫蓝兔的故事讲解原型模式
什么是原型模式
原型(Prototype)模式的定义如下: 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。在生活中复制的例子非常多,这里不一一列举了。
优点
1、Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
2、可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点
1、需要为每一个类都配置一个 clone 方法
2、clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
3、当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
应用场景
在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。
浅克隆
案例:克隆虹猫
浅克隆一个虹猫,外表特征一样,但是只有一个灵魂。
克隆虹猫身体受到伤害,本体虹猫不受影响。
克隆虹猫精神受到伤害,本体虹猫也受到同样的伤害。
代码实现
虹猫灵魂状态类
这里声明了虹猫的灵魂状态
public class Hong { //虹猫的灵魂状态 private String lh; Hong(String lh) { this.lh = lh; } Hong() { } public String getLh() { return lh; } public void setLh(String lh) { this.lh = lh; } }
虹猫个体类
实现了Cloneable 接口,并且有虹猫的身体状态和灵魂状态等属性。
public class Qian implements Cloneable { private String shou; private String jiao; private String yan; private Hong hong; Qian() { } Qian(String shou, String jiao, String yan, Hong hong) { this.hong = hong; this.shou = shou; this.jiao = jiao; this.yan = yan; } public Qian clone() throws CloneNotSupportedException { return (Qian) super.clone(); } public String getShou() { return shou; } public void setShou(String shou) { this.shou = shou; } public String getJiao() { return jiao; } public void setJiao(String jiao) { this.jiao = jiao; } public String getYan() { return yan; } public void setYan(String yan) { this.yan = yan; } public Hong getHong() { return hong; } public void setHong(Hong hong) { this.hong = hong; } }
测试类
这里测试一下浅克隆的效果:
浅克隆一个虹猫,外表特征一样,但是只有一个灵魂。
克隆虹猫身体受到伤害,本体虹猫不受影响。
克隆虹猫精神受到伤害,本体虹猫也受到同样的伤害。
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("两只手", "两只脚", "两只眼", new Hong("完整的灵魂")); Qian qian1 = qian.clone(); System.out.printf("虹猫少侠本体的身体状态:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹猫少侠一号的身体状态:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
克隆出来了一个虹猫一号,所有属性都一模一样
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("两只手", "两只脚", "两只眼", new Hong("完整的灵魂")); Qian qian1 = qian.clone(); qian1.getHong().setLh("灵魂受到攻击"); qian1.setJiao("断了一只脚"); System.out.printf("虹猫少侠本体的身体状态:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹猫少侠一号的身体状态:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
这里克隆虹猫的脚和灵魂都受到了伤害,本体虹猫的身体没有受到影响,但是灵魂却受到了伤害。
总结
一、为什么浅克隆中虹猫一号的脚受到了伤害,本体虹猫却没受到伤害?
二、为什么浅克隆中虹猫一号的灵魂受到了伤害,本体虹猫也受到了伤害?
因为创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。 两个虹猫的灵魂指向同一个内存地址,所以存储的是同一个灵魂。
深克隆
案例:克隆虹猫
深克隆一个虹猫,外表特征一样,都有独立灵魂。
克隆虹猫身体受到伤害,本体虹猫不受影响。
克隆虹猫精神受到伤害,本体虹猫也不受影响。
代码实现
虹猫灵魂状态类
这里声明了虹猫的灵魂状态,并且实现了Cloneable 接口,克隆一个虹猫灵魂
public class Hong implements Cloneable { //虹猫的灵魂状态 private String lh; Hong(String lh) { this.lh = lh; } Hong() { } public Hong clone() throws CloneNotSupportedException { return (Hong) super.clone(); } public String getLh() { return lh; } public void setLh(String lh) { this.lh = lh; } }
虹猫个体类
重写了clone方法,在clone方法中调用了hong.clone()方法克隆了一个虹猫灵魂
public class Qian implements Cloneable { private String shou; private String jiao; private String yan; private Hong hong; Qian() { } Qian(String shou, String jiao, String yan, Hong hong) { this.hong = hong; this.shou = shou; this.jiao = jiao; this.yan = yan; } public Qian clone() throws CloneNotSupportedException { Qian qian = (Qian) super.clone(); hong = hong.clone(); return qian; } public String getShou() { return shou; } public void setShou(String shou) { this.shou = shou; } public String getJiao() { return jiao; } public void setJiao(String jiao) { this.jiao = jiao; } public String getYan() { return yan; } public void setYan(String yan) { this.yan = yan; } public Hong getHong() { return hong; } public void setHong(Hong hong) { this.hong = hong; } }
测试类
这里测试一下浅克隆的效果:
深克隆一个虹猫,外表特征一样,都有独立灵魂。
克隆虹猫身体受到伤害,本体虹猫不受影响。
克隆虹猫精神受到伤害,本体虹猫也不受影响。
public class Demo { public static void main(String[] args) throws CloneNotSupportedException { Qian qian = new Qian("两只手", "两只脚", "两只眼", new Hong("完整的灵魂")); Qian qian1 = qian.clone(); qian1.getHong().setLh("灵魂受到攻击"); qian1.setJiao("断了一只脚"); System.out.printf("虹猫少侠本体的身体状态:%s,%s,%s,%s,", qian.getHong().getLh(), qian.getJiao(), qian.getShou(), qian.getYan()); System.out.println(); System.out.printf("虹猫少侠一号的身体状态:%s,%s,%s,%s,", qian1.getHong().getLh(), qian1.getJiao(), qian1.getShou(), qian1.getYan()); } }
深克隆出的虹猫完全是个独立的个体,再也不用受限制了。
总结
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
到此这篇关于Java 设计模式以虹猫蓝兔的故事讲解原型模式的文章就介绍到这了,更多相关Java 原型模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论