原型模式是创建型模式的 最后一种,类似于克隆技术,一般情况下原型模式不会单独出现,而总是和工厂模式一起使用。spring中bean的床架其实就两种,单例和原型。当你需要new的类结构比较复杂或有很多限制条件的时候可以考虑用原型模式。
原型模式的使用需要将你要复制的类实现cloneable接口,并重写Object类的clone()方法。
package com.panda.prototype;
import java.io.Serializable;
import java.sql.Date;
@SuppressWarnings("serial")
public class Panda implements Cloneable,Serializable{
private String name;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
return obj;
}
public Panda(String name, Date birthday) {
super();
this.name = name;
this.birthday = birthday;
}
public Panda() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
克隆
也分为深克隆和浅克隆,以上代码可以实现浅克隆,深克隆的实现需要重写clone方法时对类的属性一同调用clone方法才可实现。
package com.panda.prototype;
import java.sql.Date;
public class Panda2 implements Cloneable{
private String name;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Panda2 panda = (Panda2)obj;
panda.birthday = (Date) this.birthday.clone();
return obj;
}
public Panda2(String name, Date birthday) {
super();
this.name = name;
this.birthday = birthday;
}
public Panda2() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
除了以上两种实现原型模式克隆外,还有一种使用序列化化和反序列化实现深克隆的方式,不需要属性去调用clone方法
进行test测试
package com.panda.prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Date;
/**
* 浅克隆&&深克隆
* @author Administrator
*
*/
public class Test {
public static void main(String[] args) throws Exception {
//浅克隆
System.out.println("---------浅克隆-----------");
Date date = new Date(65465465421L);
Panda p1 = new Panda("福顺",date);
System.out.println("原型:"+p1.getName()+", "+p1.getBirthday());
Panda p2 = (Panda) p1.clone();
date.setTime(984564131685L);
System.out.println("原型:"+p1.getName()+", "+p1.getBirthday());
System.out.println("克隆:"+p2.getName()+", "+p2.getBirthday());
System.out.println("---------深克隆-----------");
//深克隆
Panda2 p3 = new Panda2("福来",date);
System.out.println("原型:"+p3.getName()+", "+p3.getBirthday());
Panda2 p4 = (Panda2) p3.clone();
date.setTime(984531685L);
System.out.println("原型:"+p3.getName()+", "+p3.getBirthday());
System.out.println("克隆:"+p4.getName()+", "+p4.getBirthday());
System.out.println("---序列化和反序列化实现深克隆-----");
//序列化和反序列化实现深克隆
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(p1);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Panda p5 = (Panda)ois.readObject();
System.out.println("原型:"+p1.getName()+", "+p1.getBirthday());
date.setTime(9845310285L);
System.out.println("原型:"+p1.getName()+", "+p1.getBirthday());
System.out.println("克隆:"+p5.getName()+", "+p5.getBirthday());
}
}
结果:
从以上结果可以看出浅克隆出来的对象在原有对象指向的时间改变后会跟着改变,但深克隆出来的对象将不再受原有对象所指向的时间对象改变的影响。
另外,这种模式在需要使用大量的同类对象的情况下,总体来说比new的方式效率高一些。