來源:https://blog.csdn.net/IT_charge
一、簡述
在王者榮耀商城中,玩家可以參與奪寶抽獎。奪寶抽獎分兩種,一種是積分抽獎,另一種是鑽石抽獎;在平常,兩種奪寶抽獎方式均可以通過60鑽石/積分抽獎一次,或者通過270鑽石/積分連續抽獎5次;其中,當鑽石奪寶幸運值達到201時,可以獲得稀有王者水晶,當積分奪寶幸運值達到361時,可以獲得稀有榮耀水晶;玩家可以使用王者水晶或榮耀水晶換取特定的英雄、皮膚、裝備等。
在很多情況下,可以處理某個請求的對象不止一個。很多對象都可以處理申請,而且它們構成一條鏈,請求沿着這條鏈傳遞,這條鏈就稱為職責鏈。
針對以上描述,王者榮耀中的奪寶就是責任鏈模式在王者榮耀中應用的例子。在這個問題中,玩家通過點擊60鑽石/積分抽一次或者270鑽石/積分抽五次實現抽獎結果。
具體而言,我們首先通過一個接口實現接收用戶提交的請求,再通過三個類的實例實現具體的處理請求操作;其中,通過類“60鑽石/積分抽一次”實現在14種獎品中隨機得到一個獎品、類“270鑽石/積分抽五次”實現在14種獎品中隨機得到五個獎品、類“幸運值達到一定數值之后”實現獲得稀有水晶的獎勵。
二、責任鏈模式
責任鏈模式理解: 高度概括:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系,將這些對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它為止 。
在設計Java模式時,可能需要設計很多對象來滿足用戶的請求。
責任鏈模式是使用多個對象處理用戶請求的成熟模式,責任鏈模式的關鍵是將用戶的請求分派給許多對象,這些對象被組織成責任鏈,即每個對象含有后繼對象的引用,並要求責任鏈上的每個對象,如果能處理用戶的請求,就做出處理,不再將用戶的請求傳遞給責任鏈上的下一個對象,如果不能處理用戶的請求,就必須將用戶的請求傳遞給責任鏈上的下一個對象。
責任鏈模式結構中的兩種角色:
❶ 處理者:是一個接口,負責規定具體處理者處理用戶請求的方法以及具體處理者設置后繼對象的方法;最新 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;
}
}
運行結果截圖
因為出獎品是隨機的,所以多取幾張圖作為測試。最新 Java 面試題分享給你。
第一次抽:
第二次抽:
……
第N次抽:
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.別在再滿屏的 if/ else 了,試試策略模式,真香!!
3.卧槽!Java 中的 xx ≠ null 是什么新語法?
4.Spring Boot 2.5 重磅發布,黑暗模式太炸了!
覺得不錯,別忘了隨手點贊+轉發哦!