用一个已经创建的实例作为原型,克隆(clone)该原型对象来创建一个和原型相同或相似的新对象,免去创建对象的复杂过程和细节。原型模式分浅拷贝与深拷贝两种。
浅拷贝实现方式:
1.原型类实现CLoneable接口
2.拷贝对象通过原型的clone方法获得新的实例
深拷贝实现方式:
1.原型类实现CLoneable接口
2.原型类重写clone方法,并在克隆对象同时也克隆响应的引用类型成员变量。
————————————–
以下通过国宝熊猫的克隆来理解浅拷贝与深拷贝:
熊猫类包含两个成员属性:熊猫名字与饲养员。熊猫名字为普通字符串对象,饲养员为引用对象。以下分别通过浅拷贝和深拷贝两种方式克隆熊猫对象:
浅拷贝方式:
package net.mosang.prototype; import java.util.Date; /** * * @author heiry * */ public class Panda implements Cloneable { private String name; private Feeder feeder; //重写clone方法 @Override protected Object clone() throws CloneNotSupportedException { Panda panda = (Panda) super.clone(); return panda; } //setter、getter public String getName() { return name; } public void setName(String name) { this.name = name; } public Feeder getFeeder() { return feeder; } public void setFeeder(Feeder feeder) { this.feeder = feeder; } //构造方法 public Panda(String name, Feeder feeder) { super(); this.name = name; this.feeder = feeder; } }
package net.mosang.prototype; public class Feeder { public String name; public void feed() { System.out.println("feed panda...."); } public Feeder(String name) { super(); this.name = name; } }
package net.mosang.prototype;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Feeder feeder = new Feed犀利士
er("张大胖");
Panda p1 = new Panda("pangpang",feeder);
Panda p2 = (Panda) p1.clone();
System.out.println(p1);
System.out.println(p2);
feeder.name = "张小胖";
System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name);
System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name);
}
}
运行结果:
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张小胖
可见浅拷贝方式,虽然获得了一个与原型对象一样的新对象,但是对于引用类型成员变量feeder,拷贝的是地址而不是对象本身,换句话说,两个对象的feeder指向的是同一个Feeder对象。
深拷贝方式:
重点在于重写原型类的clone方法:
package net.mosang.prototype; /** * * @author heiry * */ public class Panda implements Cloneable{ private String name; private Feeder feeder; //重写clone方法,并将引用成员变量feeder同时克隆 @Override protected Object clone() throws CloneNotSupportedException { Object obj = super.clone(); Panda panda = (Panda) obj ; panda.feeder = (Feeder)this.feeder.clone(); return panda; } //setter、getter public String getName() { return name; } public void setName(String name) { this.name = name; } public Feeder getFeeder() { return feeder; } public void setFeeder(Feeder feeder) { this.feeder = feeder; } //构造方法 public Panda(String name, Feeder feeder) { super(); this.name = name; this.feeder = feeder; } }
package net.mosang.prototype; public class Feeder implements Cloneable{ public String name; public void feed() { System.out.println("feed panda...."); } public Feeder(String name) { super(); this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
package net.mosang.prototype; public class Client { public static void main(String[] args) throws CloneNotSupportedException { Feeder feeder = new Feeder("张大胖"); Panda p1 = new Panda("pangpang",feeder); Panda p2 = (Panda) p1.clone(); System.out.println(p1); System.out.println(p2); feeder.name = "张小胖"; System.out.println("p1----->"+p1+"p1饲养员:----->"+p1.getFeeder().name); System.out.println("p2----->"+p2+"p2饲养员:----->"+p2.getFeeder().name); } }
运行结果:
net.mosang.prototype.Panda@15db9742 net.mosang.prototype.Panda@6d06d69c p1----->net.mosang.prototype.Panda@15db9742p1饲养员:----->张小胖 p2----->net.mosang.prototype.Panda@6d06d69cp2饲养员:----->张大胖
可以看到,深拷贝的引用类型成员变量也是各自独立的。