JAVA设计模式之原型模式(prototype)
2020-05-23 16:07:12来源:博客园 阅读 ()
JAVA设计模式之原型模式(prototype)
原型模式:
- 原型模式又叫克隆模式
- Java自带克隆模式
- 实现克隆模式必须实现Cloneable
- 接口,如果不实现会发生java.lang.CloneNotSupportedException异常
- 当某个类的属性已经设定好需要创建很多相同属性值的对象的时候使用clone模式非常方便
- 使用clone模式不见得比传统的new方式性能高
- 浅克隆和深克隆
先看下面的代码,没有实现Cloneable接口
package com.srr.dp.clone; /** * (原型模式)克隆模式 */ public class Appler /*implements Cloneable*/{ private String clor; private int weight; private int volume; private StringBuilder descr; public Appler(String clor) { this.clor = clor; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Appler{" + "clor='" + clor + '\'' + ", weight=" + weight + ", volume=" + volume + ", descr=" + descr + '}'; } } package com.srr.dp.clone; public class T { public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow"); Appler appler1 = (Appler) appler.clone(); System.out.println(appler1); } }
运行结果:
浅拷贝:
package com.srr.dp.clone; /** * (原型模式)克隆模式 * 浅拷贝 */ public class Appler implements Cloneable { private String clor; private int weight; private int volume; private Location loc; public Appler(String clor,int weight,int volume,Location loc) { this.clor = clor; this.weight = weight; this.volume = volume; this.loc = loc; } public String getClor() { return clor; } public void setClor(String clor) { this.clor = clor; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public Location getLoc() { return loc; } public void setLoc(Location loc) { this.loc = loc; } @Override protected Object clone() throws CloneNotSupportedException { //loc = (Locaton) loc.clone(); return super.clone(); } @Override public String toString() { return "Appler{" + "clor='" + clor + '\'' + ", weight=" + weight + ", volume=" + volume + ", loc=" + loc + '}'; } } package com.srr.dp.clone; public class Location { String name; public Location(String name){ this.name = name; } @Override public String toString() { return "Locaton{" + "name='" + name + '\'' + '}'; } } package com.srr.dp.clone; /** * 测试代码 */ public class T { public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow",1,1,new Location("洛川")); Appler appler1 = (Appler) appler.clone(); appler.setClor("red"); appler.getLoc().name = "宝鸡"; System.out.println("appler1 = "+appler1); System.out.println("appler = "+appler); } }
运行结果:
从结果发现,当改变appler 的颜色还有location的值后,拷贝的apper1对象的颜色未发生改变但是location发生了改变。
这就是浅拷贝,引用对象无法保证拷贝之后完全独立只是拷贝了地址但是地址指向的对象是共享的,
虽然String类型也是引用类型但是共享常量池所以不会有这个问题。
那么如何让引用类型拷贝之后独立呢?
那么就要使用深拷贝请看如下代码:
package com.srr.dp.clone; /** * (原型模式)克隆模式 * 浅拷贝 */ public class Appler implements Cloneable { private String clor; private int weight; private int volume; private Location loc; public Appler(String clor,int weight,int volume,Location loc) { this.clor = clor; this.weight = weight; this.volume = volume; this.loc = loc; } public String getClor() { return clor; } public void setClor(String clor) { this.clor = clor; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public Location getLoc() { return loc; } public void setLoc(Location loc) { this.loc = loc; } @Override protected Object clone() throws CloneNotSupportedException { Appler appler = (Appler)super.clone(); appler.loc = (Location) loc.clone();; return appler; } @Override public String toString() { return "Appler{" + "clor='" + clor + '\'' + ", weight=" + weight + ", volume=" + volume + ", loc=" + loc + '}'; } } package com.srr.dp.clone; public class Location implements Cloneable{ String name; public Location(String name){ this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Locaton{" + "name='" + name + '\'' + '}'; } } package com.srr.dp.clone; /** * 测试代码 */ public class T { public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow",1,1,new Location("洛川")); Appler appler1 = (Appler) appler.clone(); appler.setClor("red"); appler.getLoc().name = "宝鸡"; System.out.println("appler1 = "+appler1); System.out.println("appler = "+appler); } }
运行结果:
从结果发现,当改变appler 的颜色还有location的值后,拷贝的apper1对象的颜色未发生改变location也发生了改变。
上面说到String类型的拷贝不存在浅拷贝的问题,那么StringBuilder或者StringBuffer呢,鉴于篇幅这里使用StringBuilder来举例
请看代码:
package com.srr.dp.clone; /** * (原型模式)克隆模式 * 浅拷贝 */ public class Appler implements Cloneable { private String color; private int weight; private int volume; private Location loc; public String getColor() { return color; } public StringBuilder getDesc() { return desc; } public void setDesc(StringBuilder desc) { this.desc = desc; } private StringBuilder desc = new StringBuilder("好吃"); public Appler(String color,int weight,int volume,Location loc) { this.color = color; this.weight = weight; this.volume = volume; this.loc = loc; } public String getClor() { return color; } public void setColor(String color) { this.color = color; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public Location getLoc() { return loc; } public void setLoc(Location loc) { this.loc = loc; } @Override protected Object clone() throws CloneNotSupportedException { Appler appler = (Appler)super.clone(); appler.loc = (Location) loc.clone(); return appler; } @Override public String toString() { return "Appler{" + "color='" + color + '\'' + ", weight=" + weight + ", volume=" + volume + ", loc=" + loc + ", desc=" + desc + '}'; } } package com.srr.dp.clone; public class Location implements Cloneable{ String name; public Location(String name){ this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Locaton{" + "name='" + name + '\'' + '}'; } } package com.srr.dp.clone; /** * 测试代码 */ public class T { public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow",1,1,new Location("洛川")); Appler appler1 = (Appler) appler.clone(); appler.getDesc().append("得不得了"); appler.getLoc().name = "宝鸡"; System.out.println("appler1 = "+appler1); System.out.println("appler = "+appler); } }
运行结果:
这是是后你会发现当appler的desc值发生改变之后,apper1的值也发生改变了,说明StringBuilder的拷贝方式为浅拷贝,那么如何实现深拷贝呢
请看代码:
package com.srr.dp.clone; /** * (原型模式)克隆模式 * 浅拷贝 */ public class Appler implements Cloneable { private String color; private int weight; private int volume; private Location loc; public String getColor() { return color; } public StringBuilder getDesc() { return desc; } public void setDesc(StringBuilder desc) { this.desc = desc; } private StringBuilder desc = new StringBuilder("好吃"); public Appler(String color,int weight,int volume,Location loc) { this.color = color; this.weight = weight; this.volume = volume; this.loc = loc; } public String getClor() { return color; } public void setColor(String color) { this.color = color; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } public Location getLoc() { return loc; } public void setLoc(Location loc) { this.loc = loc; } @Override protected Object clone() throws CloneNotSupportedException { Appler appler = (Appler)super.clone(); appler.loc = (Location) loc.clone(); appler.desc = new StringBuilder(this.desc); return appler; } @Override public String toString() { return "Appler{" + "color='" + color + '\'' + ", weight=" + weight + ", volume=" + volume + ", loc=" + loc + ", desc=" + desc + '}'; } } package com.srr.dp.clone; public class Location implements Cloneable{ String name; public Location(String name){ this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Locaton{" + "name='" + name + '\'' + '}'; } } package com.srr.dp.clone; /** * 测试代码 */ public class T { public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow",1,1,new Location("洛川")); Appler appler1 = (Appler) appler.clone(); appler.getDesc().append("得不得了"); appler.getLoc().name = "宝鸡"; System.out.println("appler1 = "+appler1); System.out.println("appler = "+appler); } }
运行结果:
这是是后你会发现当appler的desc值发生改变之后,apper1的值并没有发生改变。
写到这里原型模式就介绍完了。
原创不易,请多多支持!
原文链接:https://www.cnblogs.com/sx-bj-srr/p/prototype.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash