1.使用场景:
1.1.对象类型只有在运行期才能够确定。
1.2.克隆一直对象的副本。
1.3.大同小异的一些对象。
2.UML表示
在原型模式中通常用以下的几类对象:
Client角色:使用原型对象的客户程序
Prototype角色:规定了具体原型对象必须实现的接口(如果要提供深拷贝,则必须具有实现clone的规定)
ConcretePrototype:从抽象原型派生而来,是客户程序使用的对象,即被复制的对象。此角色需要实现抽象原型角色所要求的接口。
具体的UML示意图如下:
3.代码实现
下面举一个忍者使用影分身术的例子:
定义普通忍者类:
public class Ninjia_A implements Cloneable{
private String name;//名字
private int rp;//血槽
private Ninjutsu ninjutsu;//忍术
public Ninjia_A(String name, int rp,Ninjutsu ninjutsu) {
this.name = name;
this.rp = rp;
this.ninjutsu=ninjutsu;
}
public Ninjutsu getNinjutsu() {
return ninjutsu;
}
public void setNinjutsu(Ninjutsu ninjutsu) {
this.ninjutsu = ninjutsu;
}
protected Object clone() throws CloneNotSupportedException {
Ninjia_A nn;
nn= (Ninjia_A) super.clone();
return nn;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRp() {
return rp;
}
public void setRp(int rp) {
this.rp = rp;
}
}
S级忍者:
public class Ninjia_S implements Serializable {
private static final long serialVersionUID = 2169380777227967513L;
private String name;//名字
private int rp;//血槽
private Ninjutsu ninjutsu;//忍术
public Ninjia_S(String name, int rp,Ninjutsu ninjutsu) {
this.name = name;
this.rp = rp;
this.ninjutsu=ninjutsu;
}
public Ninjutsu getNinjutsu() {
return ninjutsu;
}
public void setNinjutsu(Ninjutsu ninjutsu) {
this.ninjutsu = ninjutsu;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRp() {
return rp;
}
public void setRp(int rp) {
this.rp = rp;
}
protected Object dclone() throws CloneNotSupportedException, IOException, ClassNotFoundException {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return ois.readObject();
}
}
忍术类:
public class Ninjutsu implements Serializable {
private int damage;//破坏力
private String name;
public Ninjutsu(int damage, String name) {
this.damage = damage;
this.name = name;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类::
public class Client {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Ninjia_A kakaxi=new Ninjia_A("旗木.卡卡西",50,new Ninjutsu(500,"影分身"));
Ninjia_A kk;
try {
kk= (Ninjia_A) kakaxi.clone();
System.out.println(kakaxi.getNinjutsu()==kk.getNinjutsu());
// System.out.println(kk.getNinjutsu().getName()+" "+kk.getNinjutsu().getDamage());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
Ninjia_S naturo=new Ninjia_S("漩涡.那乳托",500,new Ninjutsu(1000,"影分身"));
Ninjia_S nn;
try {
nn= (Ninjia_S) naturo.dclone();
System.out.println(naturo.getNinjutsu()==nn.getNinjutsu());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
结论:原型模式更像一种编程的技巧,很少单独使用,注意的是在Java中,除了基本数据类型外,其他的都是引用类型,这个必须注意。
最后,附上文章的代码下载连接:
https://github.com/MemoryExplosion/design_pattern_review/tree/master/src/java/prototype