一、Protype模式简介
原型模式的特点为对象通过复制自己进行创建生成新对象,是一种对象创建型模式。
特点:
1、由原型对象自身创建目标对象(意味着具体原型类需要实现cloneable接口)。
2、目标对象是原型对象的一个克隆。通过Prottype模式创建的对象,不仅仅与目标对象具有相同的结构,还与目标对象具有相同的值。
3、根据对象克隆层次的不同,有浅克隆与深克隆。
二、实例角度介绍:
假如有一个游戏角色剑圣,剑圣有影分身技能,影分身也能分裂成多个影分身。
原型接口
public interface Blademaster{
Blademaster clone();
}
具体原型类
public class BlademasterShadow implements Blademaster,Cloneable,Serializable{
int damage;
String speed;
String skill;
int blood;
int armor;
ShadowOfShowdow shadow;
boolean isDeepClone;
BlademasterShadow(int damage,String speed,String skill,int blood,int armor,ShadowOfShowdow shadow,boolean isDeepClone) {
this.armor = armor;
this.blood = blood;
this.damage = damage;
this.skill = skill;
this.speed = speed;
this.shadow = shadow;
this.isDeepClone = isDeepClone;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
public int getArmor() {
return armor;
}
public void setArmor(int armor) {
this.armor = armor;
}
public ShadowOfShowdow getShadow() {
return shadow;
}
public void setShadow(ShadowOfShowdow shadow) {
this.shadow = shadow;
}
public boolean isDeepClone() {
return isDeepClone;
}
public void setDeepClone(boolean isDeepClone) {
this.isDeepClone = isDeepClone;
}
public void Resume() {
System.out.println("damage:" + this.damage+'\n'+
"speed:" + this.speed+'\n'+
"skill:" + this.skill+'\n'+
"blood:" + this.blood+'\n'+
"armor:" + this.armor +'\n'+ "*******************");
}
@Override
public BlademasterShadow clone(){
if(isDeepClone) {
return deepClone();
}
else {
return shallowClone();
}
}
private BlademasterShadow shallowClone() {
try {
return (BlademasterShadow) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
private BlademasterShadow deepClone() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
bis.close();
ois.close();
BlademasterShadow blademasterShadow = (BlademasterShadow) ois.readObject();
return blademasterShadow;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
class ShadowOfShowdow implements Serializable{
String whoseShadow;
ShadowOfShowdow(String whoseShadow){
this.whoseShadow = whoseShadow;
}
public String getWhoseShadow() {
return whoseShadow;
}
public void setWhoseShadow(String whoseShadow) {
this.whoseShadow = whoseShadow;
}
}
客户端测试类
public class CloneTest {
public static void main(String[] args) {
ShadowOfShowdow shadow1 = new ShadowOfShowdow("影分身1");
BlademasterShadow shadowA = new BlademasterShadow(100,"100m/s","剑刃风暴",1000,500,shadow1,true);
BlademasterShadow shadowB = shadowA.clone();
//clone生成的对象实例单独开辟空间
System.out.println("deepclone下shadowA == shadowB?" + (shadowA == shadowB));
System.out.println("deepclone下shadowASkill==shadowBSkill?" + (shadowA.getSkill() == shadowB.getSkill()));
System.out.println("deepclone下shadowA's shadow==shadowB's shadow?" +(shadowA.getShadow()==shadowB.getShadow()));
shadowA.getShadow().setWhoseShadow("影分身2");
shadowA.setSkill("平A");
shadowA.setDeepClone(false);
BlademasterShadow shadowC =shadowA.clone();
System.out.println("shallowClone下shadowA == shadowB?" +(shadowA==shadowC));
//浅克隆只克隆对象里边的基础类型变量,对于引用类型只clone了引用,未开辟新的空间
System.out.println("shallowClone下shadowASkill==shadowBSkill?" + (shadowA.getSkill() == shadowC.getSkill()));
System.out.println("shallowClone下shadowA's shadow==shadowB's shadow?" +(shadowA.getShadow()==shadowC.getShadow()));
shadowA.getShadow().setWhoseShadow("影分身3");
shadowA.Resume();
shadowB.Resume();
shadowC.Resume();
System.out.println(shadowA.getShadow().getWhoseShadow());
System.out.println(shadowB.getShadow().getWhoseShadow());
System.out.println(shadowC.getShadow().getWhoseShadow());
}
}
执行结果:
三、实例结果分析
从结果中,我们可以看到,deepclone和shallowclone都是都完整复制了原型类对象shadowA的结构,此处通过序列化生成对象的方式实现deepclone(当然也可以通过对应用类型的单独clone来实现),deepclone下所有成员地址对比都返回false,这意味着clone出来的对象shadowB与原型对象shadowA完全不关联,在这种情况下算是彻底的克隆了。再看shallowclone,其引用类型的地址对比返回结果都为true,这意味着shadowA与shadowC下的引用类型变量指向的是同一个内存地址,后边我们对shadowA的whoseshadow进行赋值,shadowC的whoseshadow也跟着改变了,但shadowB完全不受影响,这一现象也印证了前边的结论。
总结:
优点:
1、原型模式是创建型模式,其通过克隆的方式进行对象创建的效率比new的方式高(由于clone方法是有虚拟机直接复制内存块执行,所以在速度上比使用new的方式创建对象要快。)
2、当创建的对象实例较为复杂的时候或者创建对象比较损耗性能时,使用原型模式可以简化对象创建的过程,提高性能。
缺点:
实现深度克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用的时候,为了实现深度克隆,每一层对象的类都必须支持深度克隆,较为繁琐。