責(zé)任鏈模式在王者榮耀中的應(yīng)用,妙??!
點(diǎn)擊關(guān)注公眾號,Java干貨及時(shí)送達(dá)??

來源:blog.csdn.net/IT_charge/article/details/105011204/

一、簡述
在王者榮耀商城中,玩家可以參與奪寶抽獎。奪寶抽獎分兩種,一種是積分抽獎,另一種是鉆石抽獎;在平常,兩種奪寶抽獎方式均可以通過60鉆石/積分抽獎一次,或者通過270鉆石/積分連續(xù)抽獎5次;其中,當(dāng)鉆石奪寶幸運(yùn)值達(dá)到201時(shí),可以獲得稀有王者水晶,當(dāng)積分奪寶幸運(yùn)值達(dá)到361時(shí),可以獲得稀有榮耀水晶;玩家可以使用王者水晶或榮耀水晶換取特定的英雄、皮膚、裝備等。
在很多情況下,可以處理某個(gè)請求的對象不止一個(gè)。很多對象都可以處理申請,而且它們構(gòu)成一條鏈,請求沿著這條鏈傳遞,這條鏈就稱為職責(zé)鏈。
針對以上描述,王者榮耀中的奪寶就是責(zé)任鏈模式在王者榮耀中應(yīng)用的例子。在這個(gè)問題中,玩家通過點(diǎn)擊60鉆石/積分抽一次或者270鉆石/積分抽五次實(shí)現(xiàn)抽獎結(jié)果。
具體而言,我們首先通過一個(gè)接口實(shí)現(xiàn)接收用戶提交的請求,再通過三個(gè)類的實(shí)例實(shí)現(xiàn)具體的處理請求操作;其中,通過類“60鉆石/積分抽一次”實(shí)現(xiàn)在14種獎品中隨機(jī)得到一個(gè)獎品、類“270鉆石/積分抽五次”實(shí)現(xiàn)在14種獎品中隨機(jī)得到五個(gè)獎品、類“幸運(yùn)值達(dá)到一定數(shù)值之后”實(shí)現(xiàn)獲得稀有水晶的獎勵。
二、責(zé)任鏈模式
責(zé)任鏈模式理解: 高度概括:使多個(gè)對象都有機(jī)會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系,將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個(gè)對象處理它為止 。
在設(shè)計(jì)Java模式時(shí),可能需要設(shè)計(jì)很多對象來滿足用戶的請求。
責(zé)任鏈模式是使用多個(gè)對象處理用戶請求的成熟模式,責(zé)任鏈模式的關(guān)鍵是將用戶的請求分派給許多對象,這些對象被組織成責(zé)任鏈,即每個(gè)對象含有后繼對象的引用,并要求責(zé)任鏈上的每個(gè)對象,如果能處理用戶的請求,就做出處理,不再將用戶的請求傳遞給責(zé)任鏈上的下一個(gè)對象,如果不能處理用戶的請求,就必須將用戶的請求傳遞給責(zé)任鏈上的下一個(gè)對象。
責(zé)任鏈模式結(jié)構(gòu)中的兩種角色:
? 處理者:是一個(gè)接口,負(fù)責(zé)規(guī)定具體處理者處理用戶請求的方法以及具體處理者設(shè)置后繼對象的方法;
?具體處理者:具體處理者是實(shí)現(xiàn)處理者接口的類的實(shí)例。具體處理者通過調(diào)用處理者接口規(guī)定的方法,處理用戶的請求,即在接到用戶的請求后,處理者將調(diào)用接口規(guī)定的方法,在執(zhí)行該方法的過程中,如果發(fā)現(xiàn)能處理用戶的請求,就處理有關(guān)數(shù)據(jù);否則就反饋無法處理的信息給用戶,然后將用戶的請求傳遞給自己的后繼對象。

責(zé)任鏈模式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
①責(zé)任鏈中的對象只和自己的后繼是低耦合關(guān)系和其他對象毫無關(guān)聯(lián);
②當(dāng)在處理者中分配職責(zé)時(shí),責(zé)任鏈給應(yīng)用程序更多的靈活性;
③應(yīng)用程序可以動態(tài)的增加,刪除處理者或重新指派處理者的職責(zé);
④應(yīng)用程序可以動態(tài)的改變處理者之間的先后順序;
⑤使用責(zé)任鏈的用戶不必知道處理者的信息,用戶不會知道到底是哪個(gè)對象處理了他的請求;
缺點(diǎn):
①不能保證請求一定被接收:沒有明確接收者,不能確保一定被處理;
②對于太長的職責(zé)鏈,影響系統(tǒng)性能。建鏈不當(dāng)可能出現(xiàn)死循環(huán)。
責(zé)任鏈模式的適用情景:
①有許多對象可以處理用戶的請求,希望程序在運(yùn)行期間自動確定處理用戶的那個(gè)對象;
②希望用戶不必明確指定接收者的情況下,向多個(gè)接收者的一個(gè)提交請求;
③程序希望動態(tài)制定可處理用戶請求的對象集合。
三、王者榮耀角度下實(shí)現(xiàn)責(zé)任鏈模式結(jié)構(gòu)圖及代碼
實(shí)現(xiàn)此責(zé)任鏈模式的UML類圖

eclipse結(jié)構(gòu)圖

主函數(shù)【應(yīng)用(Application)】
Application.java
package?angle_responsibility;
/*
*?測試應(yīng)用類
*/
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;????//責(zé)任鏈上的對象
????public?void?createChain(){???????//建立責(zé)任鏈
????????diamond60=new?Diamond60DrawAPrize();
????????diamond270=new?Diamond270DrawFivePrizes();
????????rareDiamond=new?RareCrystalOfKings();
????????diamond60.setNextHandler(diamond270);
????????diamond270.setNextHandler(rareDiamond);
????}
????public?void?reponseClient(int?number){??//響應(yīng)用戶的請求
????????diamond60.handleRequest(number);
????}
????public?static?void?main(String?args[]){
???????Application??application=new??Application();
???????application.createChain();
???????System.out.println("當(dāng)點(diǎn)擊“60鉆石”抽一次時(shí):");
???????System.out.print("[購買成功]");
???????application.reponseClient(60);
???????System.out.println("---------------------------");
???????System.out.println("當(dāng)點(diǎn)擊“270鉆石”抽五次時(shí):");
???????System.out.print("[購買成功]");
???????application.reponseClient(270);
???????System.out.println("---------------------------");
???????System.out.println("當(dāng)鉆石抽獎“幸運(yùn)值達(dá)201時(shí)”:");
???????System.out.print("[購買成功]");
???????application.reponseClient(201);
????}
}
處理者(Handler)
Handler.java
package?angle_responsibility;
/*
*?角色1:處理者?:是一個(gè)接口,負(fù)責(zé)規(guī)定具體處理者處理用戶請求的方法以及具體處理者設(shè)置后繼對象的方法
*/
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:具體處理者?:具體處理者是實(shí)現(xiàn)處理者接口的類的實(shí)例
*?????????????????具體處理者通過調(diào)用處理者接口規(guī)定的方法,處理用戶的請求
*?????????????????即在接到用戶的請求后,處理者將調(diào)用接口規(guī)定的方法,在執(zhí)行該方法的過程中
*?????????????????如果發(fā)現(xiàn)能處理用戶的請求,就處理有關(guān)數(shù)據(jù)
*?????????????????否則就反饋無法處理的信息給用戶,然后將用戶的請求傳遞給自己的后繼對象
*/
import?angle_responsibility.Handler;
public?class?Diamond60DrawAPrize?implements?Handler{
??private?Handler?handler;??????//存放當(dāng)前處理者后繼的Hander接口變量
?????public?void?handleRequest(int?number){
?????if(number==60){??????????????//60鉆石抽一次
??????String?random?=?"";
????????????String[]?doc?=?{"白起",?"夏侯惇",?"甄姬",?"金幣288","小喇叭5","銘文碎片1600",?"銘文碎片400","銘文碎片100",?"銘文碎片25",?"愛心氣球(3日)",?"親密玫瑰","鉆石48","龍域領(lǐng)主體驗(yàn)卡"};
????????????int?index?=?(int)?(Math.random()?*?doc.length);?????????//隨機(jī)選取其一輸出
????????????random?=?doc[index];
????????????System.out.println(random);
?????}
?????else
??????handler.handleRequest(number);?????//將請求傳遞給下一個(gè)處理者
????????}
??????public?void?setNextHandler(Handler?handler){
?????????this.handler=handler;
????}
}
Diamond270DrawFivePrizes,java
package?angle_responsibility;
/*
*?角色2.2:具體處理者?:具體處理者是實(shí)現(xiàn)處理者接口的類的實(shí)例
*?????????????????具體處理者通過調(diào)用處理者接口規(guī)定的方法,處理用戶的請求
*?????????????????即在接到用戶的請求后,處理者將調(diào)用接口規(guī)定的方法,在執(zhí)行該方法的過程中
*?????????????????如果發(fā)現(xiàn)能處理用戶的請求,就處理有關(guān)數(shù)據(jù)
*?????????????????否則就反饋無法處理的信息給用戶,然后將用戶的請求傳遞給自己的后繼對象
*/
public?class?Diamond270DrawFivePrizes?implements?Handler{
?private?Handler?handler;??????//存放當(dāng)前處理者后繼的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","龍域領(lǐng)主體驗(yàn)卡"};
???????????int?index?=?(int)?(Math.random()?*?doc.length);??????//隨機(jī)選取其五輸出
???????????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);??????//將請求傳遞給下一個(gè)處理者
???????}
?????public?void?setNextHandler(Handler?handler){
????????this.handler=handler;
???}
}
RareCrystalOfKings.java
package?angle_responsibility;
/*
*?角色2.3:具體處理者?:具體處理者是實(shí)現(xiàn)處理者接口的類的實(shí)例
*?????????????????具體處理者通過調(diào)用處理者接口規(guī)定的方法,處理用戶的請求
*?????????????????即在接到用戶的請求后,處理者將調(diào)用接口規(guī)定的方法,在執(zhí)行該方法的過程中
*?????????????????如果發(fā)現(xiàn)能處理用戶的請求,就處理有關(guān)數(shù)據(jù)
*?????????????????否則就反饋無法處理的信息給用戶,然后將用戶的請求傳遞給自己的后繼對象
*/
public?class?RareCrystalOfKings?implements?Handler{
?private?Handler?handler;??????//存放當(dāng)前處理者后繼的Hander接口變量
????public?void?handleRequest(int?number){
????if(number==201){???????????????//當(dāng)幸運(yùn)值滿201時(shí),出稀有水晶
???????????System.out.println("【稀有】王者水晶");
????}
????else
????????????handler.handleRequest(number);??????//將請求傳遞給下一個(gè)處理者
???????}
?????public?void?setNextHandler(Handler?handler){
????????this.handler=handler;
???}
}
運(yùn)行結(jié)果截圖
因?yàn)槌霆勂肥请S機(jī)的,所以多取幾張圖作為測試
第一次抽:

第二次抽:

第N次抽:

最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)

