原型模式:
原型模式又叫克隆模式
Java自带克隆模式
实现克隆模式必须实现Cloneable
接口,如果不实现会发生java.lang.CloneNotSupportedException异常
当某个类的属性已经设定好需要创建很多相同属性值的对象的时候使用clone模式非常方便
使用clone模式不见得比传统的new方式性能高
浅克隆和深克隆
先看下面的代码,没有实现Cloneable接口
packagecom.srr.dp.clone;/*** (原型模式)克隆模式*/
public class Appler /*implements Cloneable*/{privateString clor;private intweight;private intvolume;privateStringBuilder descr;publicAppler(String clor) {this.clor =clor;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
@OverridepublicString toString() {return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", descr=" + descr +
'}';
}
}packagecom.srr.dp.clone;public classT {public static void main(String[] args) throwsCloneNotSupportedException {
Appler appler= new Appler("yellow");
Appler appler1=(Appler) appler.clone();
System.out.println(appler1);
}
}
运行结果:
浅拷贝:
packagecom.srr.dp.clone;/*** (原型模式)克隆模式
* 浅拷贝*/
public class Appler implementsCloneable {privateString clor;private intweight;private intvolume;privateLocation loc;public Appler(String clor,int weight,intvolume,Location loc) {this.clor =clor;this.weight =weight;this.volume =volume;this.loc =loc;
}publicString getClor() {returnclor;
}public voidsetClor(String clor) {this.clor =clor;
}public intgetWeight() {returnweight;
}public void setWeight(intweight) {this.weight =weight;
}public intgetVolume() {returnvolume;
}public void setVolume(intvolume) {this.volume =volume;
}publicLocation getLoc() {returnloc;
}public voidsetLoc(Location loc) {this.loc =loc;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {//loc = (Locaton) loc.clone();
return super.clone();
}
@OverridepublicString toString() {return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
'}';
}
}packagecom.srr.dp.clone;public classLocation {
String name;publicLocation(String name){this.name =name;
}
@OverridepublicString toString() {return "Locaton{" +
"name='" + name + '\'' +
'}';
}
}packagecom.srr.dp.clone;/*** 测试代码*/
public classT {public static void main(String[] args) throwsCloneNotSupportedException {
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类型也是引用类型但是共享常量池所以不会有这个问题。
那么如何让引用类型拷贝之后独立呢?
那么就要使用深拷贝请看如下代码:
packagecom.srr.dp.clone;/*** (原型模式)克隆模式
* 浅拷贝*/
public class Appler implementsCloneable {privateString clor;private intweight;private intvolume;privateLocation loc;public Appler(String clor,int weight,intvolume,Location loc) {this.clor =clor;this.weight =weight;this.volume =volume;this.loc =loc;
}publicString getClor() {returnclor;
}public voidsetClor(String clor) {this.clor =clor;
}public intgetWeight() {returnweight;
}public void setWeight(intweight) {this.weight =weight;
}public intgetVolume() {returnvolume;
}public void setVolume(intvolume) {this.volume =volume;
}publicLocation getLoc() {returnloc;
}public voidsetLoc(Location loc) {this.loc =loc;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {
Appler appler= (Appler)super.clone();
appler.loc=(Location) loc.clone();;returnappler;
}
@OverridepublicString toString() {return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
'}';
}
}packagecom.srr.dp.clone;public class Location implementsCloneable{
String name;publicLocation(String name){this.name =name;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
@OverridepublicString toString() {return "Locaton{" +
"name='" + name + '\'' +
'}';
}
}packagecom.srr.dp.clone;/*** 测试代码*/
public classT {public static void main(String[] args) throwsCloneNotSupportedException {
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来举例
请看代码:
packagecom.srr.dp.clone;/*** (原型模式)克隆模式
* 浅拷贝*/
public class Appler implementsCloneable {privateString color;private intweight;private intvolume;privateLocation loc;publicString getColor() {returncolor;
}publicStringBuilder getDesc() {returndesc;
}public voidsetDesc(StringBuilder desc) {this.desc =desc;
}private StringBuilder desc = new StringBuilder("好吃");public Appler(String color,int weight,intvolume,Location loc) {this.color =color;this.weight =weight;this.volume =volume;this.loc =loc;
}publicString getClor() {returncolor;
}public voidsetColor(String color) {this.color =color;
}public intgetWeight() {returnweight;
}public void setWeight(intweight) {this.weight =weight;
}public intgetVolume() {returnvolume;
}public void setVolume(intvolume) {this.volume =volume;
}publicLocation getLoc() {returnloc;
}public voidsetLoc(Location loc) {this.loc =loc;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {
Appler appler= (Appler)super.clone();
appler.loc=(Location) loc.clone();returnappler;
}
@OverridepublicString toString() {return "Appler{" +
"color='" + color + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
", desc=" + desc +
'}';
}
}packagecom.srr.dp.clone;public class Location implementsCloneable{
String name;publicLocation(String name){this.name =name;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
@OverridepublicString toString() {return "Locaton{" +
"name='" + name + '\'' +
'}';
}
}packagecom.srr.dp.clone;/*** 测试代码*/
public classT {public static void main(String[] args) throwsCloneNotSupportedException {
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的拷贝方式为浅拷贝,那么如何实现深拷贝呢
请看代码:
packagecom.srr.dp.clone;/*** (原型模式)克隆模式
* 浅拷贝*/
public class Appler implementsCloneable {privateString color;private intweight;private intvolume;privateLocation loc;publicString getColor() {returncolor;
}publicStringBuilder getDesc() {returndesc;
}public voidsetDesc(StringBuilder desc) {this.desc =desc;
}private StringBuilder desc = new StringBuilder("好吃");public Appler(String color,int weight,intvolume,Location loc) {this.color =color;this.weight =weight;this.volume =volume;this.loc =loc;
}publicString getClor() {returncolor;
}public voidsetColor(String color) {this.color =color;
}public intgetWeight() {returnweight;
}public void setWeight(intweight) {this.weight =weight;
}public intgetVolume() {returnvolume;
}public void setVolume(intvolume) {this.volume =volume;
}publicLocation getLoc() {returnloc;
}public voidsetLoc(Location loc) {this.loc =loc;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {
Appler appler= (Appler)super.clone();
appler.loc=(Location) loc.clone();
appler.desc= new StringBuilder(this.desc);returnappler;
}
@OverridepublicString toString() {return "Appler{" +
"color='" + color + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
", desc=" + desc +
'}';
}
}packagecom.srr.dp.clone;public class Location implementsCloneable{
String name;publicLocation(String name){this.name =name;
}
@Overrideprotected Object clone() throwsCloneNotSupportedException {return super.clone();
}
@OverridepublicString toString() {return "Locaton{" +
"name='" + name + '\'' +
'}';
}
}packagecom.srr.dp.clone;/*** 测试代码*/
public classT {public static void main(String[] args) throwsCloneNotSupportedException {
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的值并没有发生改变。
写到这里原型模式就介绍完了。
原创不易,请多多支持!