共计 6288 个字符,预计需要花费 16 分钟才能阅读完成。
一、简述
在王者光荣商城中,玩家能够参加夺宝抽奖。夺宝抽奖分两种,一种是积分抽奖,另一种是钻石抽奖;在平时,两种夺宝抽奖形式均能够通过 60 钻石 / 积分抽奖一次,或者通过 270 钻石 / 积分间断抽奖 5 次;其中,当钻石夺宝幸运值达到 201 时,能够取得罕见王者水晶,当积分夺宝幸运值达到 361 时,能够取得罕见光荣水晶;玩家能够应用王者水晶或光荣水晶换取特定的英雄、皮肤、配备等。
在很多状况下,能够解决某个申请的对象不止一个。很多对象都能够解决申请,而且它们形成一条链,申请沿着这条链传递,这条链就称为职责链。
针对以上形容,王者光荣中的夺宝就是责任链模式在王者光荣中利用的例子。在这个问题中,玩家通过点击 60 钻石 / 积分抽一次或者 270 钻石 / 积分抽五次实现抽奖后果。
具体而言,咱们首先通过一个接口实现接管用户提交的申请,再通过三个类的实例实现具体的解决申请操作;其中,通过类“60 钻石 / 积分抽一次”实现在 14 种奖品中随机失去一个奖品、类“270 钻石 / 积分抽五次”实现在 14 种奖品中随机失去五个奖品、类“幸运值达到肯定数值之后”实现取得罕见水晶的处分。
二、责任链模式
责任链模式了解: 高度概括:使多个对象都有机会解决申请,从而防止申请的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该申请,直到有一个对象解决它为止。
在设计 Java 模式时,可能须要设计很多对象来满足用户的申请。
责任链模式是应用多个对象解决用户申请的成熟模式,责任链模式的要害是将用户的申请分派给许多对象,这些对象被组织成责任链,即每个对象含有后继对象的援用,并要求责任链上的每个对象,如果能解决用户的申请,就做出解决,不再将用户的申请传递给责任链上的下一个对象,如果不能解决用户的申请,就必须将用户的申请传递给责任链上的下一个对象。
责任链模式构造中的两种角色:
❶ _解决者_:是一个接口,负责规定具体解决者解决用户申请的办法以及具体解决者设置后继对象的办法;
❷_具体解决者_:具体解决者是实现解决者接口的类的实例。具体解决者通过调用解决者接口规定的办法,解决用户的申请,即在接到用户的申请后,解决者将调用接口规定的办法,在执行该办法的过程中,如果发现能解决用户的申请,就解决无关数据;否则就反馈无奈解决的信息给用户,而后将用户的申请传递给本人的后继对象。
责任链模式的 UML 类图:
责任链模式的优缺点:
长处:
①责任链中的对象只和本人的后继是低耦合关系和其余对象毫无关联;
②当在解决者中调配职责时,责任链给应用程序更多的灵活性;
③应用程序能够动静的减少,删除解决者或从新指派解决者的职责;
④应用程序能够动静的扭转解决者之间的先后顺序;
⑤应用责任链的用户不用晓得解决者的信息,用户不会晓得到底是哪个对象解决了他的申请;
毛病:
①不能保障申请肯定被接管:没有明确接收者,不能确保肯定被解决;
②对于太长的职责链,影响零碎性能。建链不当可能呈现死循环。
责任链模式的实用情景:
①有许多对象能够解决用户的申请,心愿程序在运行期间主动确定解决用户的那个对象;
②心愿用户不用明确指定接收者的状况下,向多个接收者的一个提交申请;
③程序心愿动静制订可解决用户申请的对象汇合。
三、王者光荣角度下实现责任链模式结构图及代码
实现此责任链模式的 UML 类图
eclipse 结构图
主函数【利用(Application)】
Application.java
package angle_responsibility;
/*
* 测试利用类
*/
import angle_responsibility.Application;
import angle_responsibility.Diamond60DrawAPrize;
import angle_responsibility.Handler;
import angle_responsibility.Diamond270DrawFivePrizes;
import angle_responsibility.RareCrystalOfKings;
public class Application {
private Handler diamond60,diamond270,rareDiamond; // 责任链上的对象
public void createChain(){ // 建设责任链
diamond60=new Diamond60DrawAPrize();
diamond270=new Diamond270DrawFivePrizes();
rareDiamond=new RareCrystalOfKings();
diamond60.setNextHandler(diamond270);
diamond270.setNextHandler(rareDiamond);
}
public void reponseClient(int number){ // 响应用户的申请
diamond60.handleRequest(number);
}
public static void main(String args[]){Application application=new Application();
application.createChain();
System.out.println("当点击“60 钻石”抽一次时:");
System.out.print("[ 购买胜利]");
application.reponseClient(60);
System.out.println("---------------------------");
System.out.println("当点击“270 钻石”抽五次时:");
System.out.print("[ 购买胜利]");
application.reponseClient(270);
System.out.println("---------------------------");
System.out.println("当钻石抽奖“幸运值达 201 时”:");
System.out.print("[ 购买胜利]");
application.reponseClient(201);
}
}
解决者(Handler)
Handler.java
package angle_responsibility;
/*
* 角色 1:解决者 : 是一个接口,负责规定具体解决者解决用户申请的办法以及具体解决者设置后继对象的办法
*/
import angle_responsibility.Handler;
public interface Handler {public abstract void handleRequest(int number); // 具体解决用户申请 60 钻石抽一次还是 270 钻石抽五次
public abstract void setNextHandler(Handler handler);
}
具体解决者(ConcreteHandler)
Diamond60DrawAPrize .java
package angle_responsibility;
/*
* 角色 2.1:具体解决者:具体解决者是实现解决者接口的类的实例
* 具体解决者通过调用解决者接口规定的办法,解决用户的申请
* 即在接到用户的申请后,解决者将调用接口规定的办法,在执行该办法的过程中
* 如果发现能解决用户的申请,就解决无关数据
* 否则就反馈无奈解决的信息给用户,而后将用户的申请传递给本人的后继对象
*/
import angle_responsibility.Handler;
public class Diamond60DrawAPrize implements Handler{
private Handler handler; // 寄存以后解决者后继的 Hander 接口变量
public void handleRequest(int number){if(number==60){ //60 钻石抽一次
String random = "";
String[] doc = {"白起", "夏侯惇", "甄姬", "金币 288","小喇叭 5","铭文碎片 1600", "铭文碎片 400","铭文碎片 100", "铭文碎片 25", "爱心气球(3 日)", "密切玫瑰","钻石 48","龙域领主体验卡"};
int index = (int) (Math.random() * doc.length); // 随机选取其一输入
random = doc[index];
System.out.println(random);
}
else
handler.handleRequest(number); // 将申请传递给下一个解决者
}
public void setNextHandler(Handler handler){this.handler=handler;}
}
Diamond270DrawFivePrizes,java
package angle_responsibility;
/*
* 角色 2.2:具体解决者:具体解决者是实现解决者接口的类的实例
* 具体解决者通过调用解决者接口规定的办法,解决用户的申请
* 即在接到用户的申请后,解决者将调用接口规定的办法,在执行该办法的过程中
* 如果发现能解决用户的申请,就解决无关数据
* 否则就反馈无奈解决的信息给用户,而后将用户的申请传递给本人的后继对象
*/
public class Diamond270DrawFivePrizes implements Handler{
private Handler handler; // 寄存以后解决者后继的 Hander 接口变量
public void handleRequest(int number){if(number==270){ //270 钻石抽五次
String random,random1,random2,random3,random4 = "";
String[] doc = {"白起", "夏侯惇", "甄姬", "金币 288","小喇叭 5","铭文碎片 1600", "铭文碎片 400","铭文碎片 100", "铭文碎片 25", "爱心气球(3 日)", "密切玫瑰","钻石 48","龙域领主体验卡"};
int index = (int) (Math.random() * doc.length); // 随机选取其五输入
random = doc[index];
System.out.print(random+"、");
int index1 = (int) (Math.random() * doc.length);
random1 = doc[index1];
System.out.print(random1+"、");
int index2 = (int) (Math.random() * doc.length);
random2 = doc[index2];
System.out.print(random2+"、");
int index3 = (int) (Math.random() * doc.length);
random3 = doc[index3];
System.out.print(random3+"、");
int index4 = (int) (Math.random() * doc.length);
random4 = doc[index4];
System.out.println(random4);
}
else
handler.handleRequest(number); // 将申请传递给下一个解决者
}
public void setNextHandler(Handler handler){this.handler=handler;}
}
RareCrystalOfKings.java
package angle_responsibility;
/*
* 角色 2.3:具体解决者:具体解决者是实现解决者接口的类的实例
* 具体解决者通过调用解决者接口规定的办法,解决用户的申请
* 即在接到用户的申请后,解决者将调用接口规定的办法,在执行该办法的过程中
* 如果发现能解决用户的申请,就解决无关数据
* 否则就反馈无奈解决的信息给用户,而后将用户的申请传递给本人的后继对象
*/
public class RareCrystalOfKings implements Handler{
private Handler handler; // 寄存以后解决者后继的 Hander 接口变量
public void handleRequest(int number){if(number==201){ // 当幸运值满 201 时,出罕见水晶
System.out.println("【罕见】王者水晶");
}
else
handler.handleRequest(number); // 将申请传递给下一个解决者
}
public void setNextHandler(Handler handler){this.handler=handler;}
}
运行后果截图
_因为出奖品是随机的,所以多取几张图作为测试_。
第一次抽:
第二次抽:
……
第 N 次抽: