在王者荣耀中,克隆模式算是一个人气比较高的娱乐模式了,因为该模式下双方可以各有五个一模一样的英雄,可以带给玩家不同的游戏体验,特别是有一些比较好玩的英雄,五个一起用就太强势了! 在克隆模式中,虽然双方五个英雄名字都一样,但是,玩家又根据喜好及玩法不同可以给同一英雄佩戴不同的铭文、皮肤、召唤师技能等。 本实例就是运用王者荣耀中的克隆模式来说明程序设计模式中的原型模式的。设计者在设计时就已经考虑到,克隆模式中有很多的相同的英雄,如果每一个都实例出来浪费资源、时间和精力,同样日后修改起来也算是繁琐的。所以可以通过原型模式克隆出多个相同英雄,这样就解决了上述让人头疼的问题。 具体而言,本实例是通过“深度克隆”实现玩家所有需求的。在设计时,已经考虑到:如果调用clone()方法的当前对象——本队英雄拥有的成员变量——具体每个玩家对英雄、皮肤、铭文等的需求是一个对象,那么clone()方法仅仅复制了当前对象所拥有的对象的引用,并没有复制这个对象所拥有的变量,这就是使clone()方法返回的新对象和当前对象拥有一个相同的对象,未能实现完全意义的复制。很显然,当前对象的成员变量中可能还会有其它对象。所以使用clone()方法复制对象有许多细节需要用户考虑,比如在重写clone()方法时,必须也要对当前对象中的对象进行复制,这样一来就涉及到了深度克隆的问题。于是乎,本实例Teammates.java和Enemies.java中,Prototype类和Serializable类的对象使用clone()方法复制自己,并处理了深度克隆问题。具体处理办法及代码运行效果图见第三部分。
原型模式理解: 高度概括:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。 在某些情况下,可能不希望反复使用类的构造方法创建许多对象,而是希望用该类创建一个对象后,以该对象为原型得到该对象的若干个复制品。也就是说,将一个对象定义为原型对象,要求该原型对象提供一个方法,使该原型对象调用此方法,可以复制一个和自己完全相同状态的同类型对象,即该方法克隆原型对象得到一个新对象。 原型对象与以它为原型“克隆”出的新对象,可以分别独立地变化。也就是说,原型对象改变其状态,不会影响到以他为原型所“克隆”出的新对象,反之也一样。 原型模式是从一个对象出发,得到一个和自己有相同状态的新对象的成熟模式,该模式的关键是将一个对象定义为原型,并为其提供复制自己的方法。
原型模式结构中的三种角色: ①抽象原型(Prototype):一个接口,负责定义对象复制自身的方法(如果要提供深拷贝,则必须具有实现clone的规定); ②具体原型(ConcretePrototype):实现Prototype接口的类,具体原型实现抽象圆形中的方法,以便所创建的对象调用该方法复制自己; ③客户(Client)角色:使用原型对象的客户程序。
原型模式的UML类图:
原型模式的优缺点: 优点: ①当创建类的新实例的代价更大时,使用原型模式复制一个已有的实例可以提高创建新实例的效率; ②可以动态地保存当前对象的状态,在运行时可以随时使用对象流保存当前对象的一个复制品; ③可以在运行时创建新的对象,而无需创建一系列类和继承结构(Prototype模式克隆一个原型而不是请求一个工厂方法去产生一个新的对象); ④可以动态的添加、删除原型的复制品; ⑤用类动态配置应用 一些运行时刻环境允许动态将类装载到应用中; 缺点: ①每一个抽象原型Prototype的子类都必须实现clone操作,而实现clone函数可能会很困难。比如说,当所考虑的类已经存在时就难以新增clone操作,当内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能也会很困难的。 ②需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说并不是很难,但对已有的类进行改造时,不一定是一件容易的事情,必须修改其源代码,违背了"开—闭原则"。
原型模式涉及的设计原则: ① 为交互对象之间的松耦合设计而努力; ② 软件实体应该是可以扩展的,但是不可修改的。
原型模式的适用情景: ①程序需要从一个对象出发,得到若干个和其状态相同,并可独立变化其状态的对象时; ②当对象的创建需要独立于它的构造过程和表示时; ③一个类创建实例状态不是很多,那么就可以将这个类的一个实例定义为原型,那么通过复制该原型得到新的实例可能比重新使用类的构造方法创建新实例更方便。
该原型模式下实现王者荣耀代码的UML类图
eclipse结构图
主函数【应用(Application)】 Application.java
package angle_prototypePattern;
import angle_prototypePattern.Teammates;
import angle_prototypePattern.Enemies;
public class Application{
public static void main(String args[]){
System.out.println("【克隆模式】匹配成功!请您选择英雄");
System.out.println("");
System.out.println("☆我方最终选定英雄“百里玄策”出战!");
System.out.println("☆敌方最终选定英雄“夏侯惇”出战!");
System.out.println("----------------------------------------------------");
Teammates teammates=new Teammates();
teammates.setSkill(new StringBuffer("治疗"));
teammates.setSkin(new StringBuffer("嚣狂之镰"));
System.out.println("☆我方");
System.out.println("英雄“百里玄策”默认召唤师技能【"+teammates.getSkill()+"】、皮肤【"+teammates.getSkin()+"】");
try{
Teammates teammatesCopy1=(Teammates)teammates.cloneMe();
Teammates teammatesCopy2=(Teammates)teammates.cloneMe();
Teammates teammatesCopy3=(Teammates)teammates.cloneMe();
Teammates teammatesCopy4=(Teammates)teammates.cloneMe();
Teammates teammatesCopy5=(Teammates)teammates.cloneMe();
teammatesCopy1.setSkill(new StringBuffer("闪现"));
teammatesCopy2.setSkill(new StringBuffer("惩击"));
teammatesCopy3.setSkill(new StringBuffer("狂暴"));
teammatesCopy4.setSkin(new StringBuffer("威尼斯狂欢"));
teammatesCopy5.setSkin(new StringBuffer("白虎志"));
System.out.println(" 玩家一保留默认召唤师技能【"+teammates.getSkill()+"】、皮肤【"+teammates.getSkin()+"】");
System.out.println(" 玩家二将召唤师技能改为【"+teammatesCopy1.getSkill()+"】、皮肤【"+teammatesCopy4.getSkin()+"】");
System.out.println(" 玩家三将召唤师技能改为【"+teammatesCopy2.getSkill()+"】、皮肤【"+teammatesCopy5.getSkin()+"】");
System.out.println(" 玩家四将召唤师技能改为【"+teammatesCopy3.getSkill()+"】、皮肤保留默认【"+teammates.getSkin()+"】");
System.out.println(" 玩家五将召唤师技能改为【"+teammatesCopy3.getSkill()+"】、皮肤【"+teammatesCopy4.getSkin()+"】");
}
catch(CloneNotSupportedException exp){}
System.out.println("---------------------------------------------------");
Enemies enemies=new Enemies();
enemies.setSkill(new StringBuffer("治疗"));
enemies.setSkin(new StringBuffer("不羁之风"));
System.out.println("☆敌方");
System.out.println("英雄“夏侯惇”默认召唤师技能【"+enemies.getSkill()+"】、皮肤【"+enemies.getSkin()+"】");
try{
Enemies enemiesCopy1=(Enemies)enemies.cloneMe();
Enemies enemiesCopy2=(Enemies)enemies.cloneMe();
Enemies enemiesCopy3=(Enemies)enemies.cloneMe();
Enemies enemiesCopy4=(Enemies)enemies.cloneMe();
Enemies enemiesCopy5=(Enemies)enemies.cloneMe();
Enemies enemiesCopy6=(Enemies)enemies.cloneMe();
Enemies enemiesCopy7=(Enemies)enemies.cloneMe();
Enemies enemiesCopy8=(Enemies)enemies.cloneMe();
enemiesCopy1.setSkill(new StringBuffer("闪现"));
enemiesCopy2.setSkill(new StringBuffer("惩击"));
enemiesCopy3.setSkill(new StringBuffer("终结"));
enemiesCopy4.setSkill(new StringBuffer("眩晕"));
enemiesCopy5.setSkin(new StringBuffer("朔风刀"));
enemiesCopy6.setSkin(new StringBuffer("乘风破浪"));
enemiesCopy7.setSkin(new StringBuffer("战争骑士"));
enemiesCopy8.setSkin(new StringBuffer("无限飓风号"));
System.out.println(" 玩家一保留默认召唤师技能【"+enemies.getSkill()+"】、皮肤【"+enemies.getSkin()+"】");
System.out.println(" 玩家二将召唤师技能改为【"+enemiesCopy1.getSkill()+"】、皮肤【"+enemiesCopy6.getSkin()+"】");
System.out.println(" 玩家三将召唤师技能改为【"+enemiesCopy3.getSkill()+"】、皮肤【"+enemiesCopy7.getSkin()+"】");
System.out.println(" 玩家四将召唤师技能改为【"+enemiesCopy4.getSkill()+"】、皮肤【"+enemiesCopy5.getSkin()+"】");
System.out.println(" 玩家五将召唤师技能改为【"+enemiesCopy2.getSkill()+"】、皮肤【"+enemiesCopy8.getSkin()+"】");
}
catch(CloneNotSupportedException exp){}
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
抽象原型 Prototype.java
package angle_prototypePattern;
public interface Prototype {
public Object cloneMe() throws CloneNotSupportedException;
}
123456
具体原型 Teammates.java
package angle_prototypePattern;
import angle_prototypePattern.Prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Teammates implements Prototype,Serializable{
StringBuffer skill,skin;
public void setSkill(StringBuffer c){
skill=c;
}
public StringBuffer getSkill(){
return skill;
}
public void setSkin(StringBuffer c){
skin=c;
}
public StringBuffer getSkin(){
return skin;
}
public Object cloneMe() throws CloneNotSupportedException{ //实现接口中的方法
Object object=null;
try{
ByteArrayOutputStream outOne=new ByteArrayOutputStream();
ObjectOutputStream outTwo=new ObjectOutputStream(outOne);
outTwo.writeObject(this); //将原型对象写入对象输出流
ByteArrayInputStream inOne=new ByteArrayInputStream(outOne.toByteArray());
ObjectInputStream inTwo=new ObjectInputStream(inOne);
object=inTwo.readObject(); //创建新的对象:原型的复制品
}
catch(Exception event){
System.out.println(event);
}
return object;
}
}
1234567891011121314151617181920212223242526272829303132333435363738394041
Enemies.java
package angle_prototypePattern;
import angle_prototypePattern.Prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Enemies implements Prototype,Serializable{
StringBuffer skill,skin;
public void setSkill(StringBuffer c){
skill=c;
}
public StringBuffer getSkill(){
return skill;
}
public void setSkin(StringBuffer c){
skin=c;
}
public StringBuffer getSkin(){
return skin;
}
public Object cloneMe() throws CloneNotSupportedException{ //实现接口中的方法
Object object=null;
try{
ByteArrayOutputStream outOne=new ByteArrayOutputStream();
ObjectOutputStream outTwo=new ObjectOutputStream(outOne);
outTwo.writeObject(this); //将原型对象写入对象输出流
ByteArrayInputStream inOne=new ByteArrayInputStream(outOne.toByteArray());
ObjectInputStream inTwo=new ObjectInputStream(inOne);
object=inTwo.readObject(); //创建新的对象:原型的复制品
}
catch(Exception event){
System.out.println(event);
}
return object;
}
}
12345678910111213141516171819202122232425262728293031323334353637383940
运行结果截图
更多设计模式在王者荣耀中的应用请点击我的设计模式在王者荣耀中的应用专栏
感谢阅读
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。