查看原文
其他

责任链模式在王者荣耀中的应用,妙啊!

大咖笔记 2022-08-09

一、简述

在王者荣耀商城中,玩家可以参与夺宝抽奖。夺宝抽奖分两种,一种是积分抽奖,另一种是钻石抽奖;在平常,两种夺宝抽奖方式均可以通过60钻石/积分抽奖一次,或者通过270钻石/积分连续抽奖5次;其中,当钻石夺宝幸运值达到201时,可以获得稀有王者水晶,当积分夺宝幸运值达到361时,可以获得稀有荣耀水晶;玩家可以使用王者水晶或荣耀水晶换取特定的英雄、皮肤、装备等。

在很多情况下,可以处理某个请求的对象不止一个。很多对象都可以处理申请,而且它们构成一条链,请求沿着这条链传递,这条链就称为职责链。

针对以上描述,王者荣耀中的夺宝就是责任链模式在王者荣耀中应用的例子。在这个问题中,玩家通过点击60钻石/积分抽一次或者270钻石/积分抽五次实现抽奖结果。

具体而言,我们首先通过一个接口实现接收用户提交的请求,再通过三个类的实例实现具体的处理请求操作;其中,通过类“60钻石/积分抽一次”实现在14种奖品中随机得到一个奖品、类“270钻石/积分抽五次”实现在14种奖品中随机得到五个奖品、类“幸运值达到一定数值之后”实现获得稀有水晶的奖励。

二、责任链模式

责任链模式理解: 高度概括:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止 。

在设计Java模式时,可能需要设计很多对象来满足用户的请求。

责任链模式是使用多个对象处理用户请求的成熟模式,责任链模式的关键是将用户的请求分派给许多对象,这些对象被组织成责任链,即每个对象含有后继对象的引用,并要求责任链上的每个对象,如果能处理用户的请求,就做出处理,不再将用户的请求传递给责任链上的下一个对象,如果不能处理用户的请求,就必须将用户的请求传递给责任链上的下一个对象。

责任链模式结构中的两种角色:

❶ 处理者:是一个接口,负责规定具体处理者处理用户请求的方法以及具体处理者设置后继对象的方法;

❷具体处理者:具体处理者是实现处理者接口的类的实例。具体处理者通过调用处理者接口规定的方法,处理用户的请求,即在接到用户的请求后,处理者将调用接口规定的方法,在执行该方法的过程中,如果发现能处理用户的请求,就处理有关数据;否则就反馈无法处理的信息给用户,然后将用户的请求传递给自己的后继对象。

责任链模式的优缺点:

优点:

①责任链中的对象只和自己的后继是低耦合关系和其他对象毫无关联;

②当在处理者中分配职责时,责任链给应用程序更多的灵活性;

③应用程序可以动态的增加,删除处理者或重新指派处理者的职责;

④应用程序可以动态的改变处理者之间的先后顺序;

⑤使用责任链的用户不必知道处理者的信息,用户不会知道到底是哪个对象处理了他的请求;

缺点:

①不能保证请求一定被接收:没有明确接收者,不能确保一定被处理;

②对于太长的职责链,影响系统性能。建链不当可能出现死循环。

另外,面试题资料公众号Java精选,回复Java面试,获取最新面试题资料,支持在线随时随地刷题。

责任链模式的适用情景:

①有许多对象可以处理用户的请求,希望程序在运行期间自动确定处理用户的那个对象;

②希望用户不必明确指定接收者的情况下,向多个接收者的一个提交请求;

③程序希望动态制定可处理用户请求的对象集合。

三、王者荣耀角度下实现责任链模式结构图及代码

实现此责任链模式的UML类图

eclipse结构图

主函数【应用(Application)】

Application.java

package angle_responsibility;

/*
* 测试应用类,公众号Java精选,有惊喜!
*/

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)

推荐:Java进阶学习资料

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次抽:

版权声明:本文为CSDN博主「荣仔!最靓的仔!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/IT_charge/article/details/105011204/

公众号“大咖笔记”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

------ THE END ------

精品资料,超赞福利!


3000+ 道 BAT 大厂面试题在线刷,最新、最全 Java 面试题!

期往精选  点击标题可跳转

为什么Spring Boot构造的jar包能直接运行?

为并发而生的 ConcurrentHashMap,基于 Java8 分析

一文彻底搞懂 cookie、session、token,和面试官扯皮就没问题了!

总在说SpringBoot内置了tomcat启动,那它的原理你说的清楚吗?

Spring 框架 @Component、@Service 等注解是如何被解析的?

Spring 源码分析(一)从基本介绍开始(系列文章基于Spring 5.0)

为什么程序员都说 SELECT * 效率低,那究竟是什么原因造成的?

23 种设计模式的通俗解释,虽然有点污,但是秒懂!

 技术交流群!

最近有很多人问,有没有读者交流群!想知道如何加入?方式很简单,兴趣相投的朋友,只需要点击下方卡片,回复“加群”,即可无套路入交流群!

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存