java责任链模式做优惠_Java实现责任链模式解决实际业务

一、问题引入

在生活中,我们会遇到填写调查问卷的情况,比如中国移动推送的通话质量问卷、京东的购物体验问卷等等,这些问卷在生成之前往往会有一套复杂的逻辑,比如题目的跳转设置、不同题目之间的互斥设置、多选题的选项之间互斥设置,以及对答案的通过性判断等等。在这些背后,某些业务的实现就可以使用到本文所介绍的责任链模式,本文也将以保存用户答题作为模拟实例引入责任链模式。

二、责任链设计模式理论知识

2.1,责任链概念

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

它的意图的是:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。主要解决的问题是:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

从概念中我们可以知道,责任链模式的核心思想是,按照设计好的有序链条逐个自动执行每一个任务。这种设计模式在分类上属于行为设计模式。

2.2,责任链类图

2.3,链的实现方式

责任链模式中的链,可以使用单向链表、List集合实现。个人感觉,单项链表在每个节点中包含下个节点的引用,在使用起来会比较方便,而且稳定。

三、用责任链设计模式解决实际业务

保存答题的具体场景为:先保存答题者,然后每个答题者可以回答多个问卷,所以答题者保存完成之后需要保存回答的是哪个答卷,最后保用户的答案。

我们用respondent单词表示答题者,用questionnaire表示答卷,用answer表示答案,在下面的代码实例中可根据单词的直译表示类的作用

下面将用实际的代码例子演示如何实现责任链,且默认使用的是SpringBoot框架。

首先我们创建责任链的处理类:RespondChainHandler

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:30:014 * @Version 1.05 * @Description 责任链模式的执行handler6 */

7 public abstract classRespondChainHandler {8 /**

9 * 节点排序字段10 **/

11 private intorder;12

13 /**

14 * 下一个节点15 **/

16 privateRespondChainHandler next;17

18 /**

19 * 执行具体任务20 *21 *@paramchainEntity 任务数据22 */

23 protected abstract voiddoHandler(ChainEntity chainEntity);24

25

26 public intgetOrder() {27 returnorder;28 }29

30 public void setOrder(intorder) {31 this.order =order;32 }33

34 publicRespondChainHandler getNext() {35 returnnext;36 }37

38 public voidsetNext(RespondChainHandler next) {39 this.next =next;40 }41 }

View Code

然后创建责任链的核心类,即责任链调用类:RespondChain

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:29:394 * @Version 1.05 * @Description 责任链模式执行保存答题任务6 */

7 public classRespondChain {8 /**

9 * 头节点10 **/

11 privateRespondChainHandler header;12

13 /**

14 * 任务执行入口15 *16 *@paramchainEntity 数据17 */

18 public voidproceed(ChainEntity chainEntity) {19 RespondChainHandler respond =header;20 while (respond != null) {21 respond.doHandler(chainEntity);22 respond =respond.getNext();23 }24 }25

26 /**

27 * 添加具体任务handler到单向链表28 *29 *@paramrespond 任务handler30 *@paramorder 排序,越小越靠前31 */

32 public void addFilter(RespondChainHandler respond, intorder) {33 respond.setOrder(order);34

35 if (header == null) {36 header =respond;37 respond.setNext(null);38 } else if (respond.getOrder() <= header.getOrder()) {//如果当前插入的排序小于header的排序,则插入到链表的头39 //插入到链表的队首位置

40 respond.setNext(header);41 header =respond;42 } else {//插入到中间某一个位置

43 RespondChainHandler previous =header;44 RespondChainHandler current =previous.getNext();45 //寻找链表中符合当前order排序的位置

46 while (current != null) {47 if (respond.getOrder() <=current.getOrder()) {48 previous.setNext(respond);49 respond.setNext(current);50 break;51 } else{52 previous =current;53 current =previous.getNext();54 }55 }56 //队尾

57 if (current == null) {58 respond.setNext(null);59 previous.setNext(respond);60 }61 }62 }63 }

View Code

创建责任链处理的数据类:ChainEntity(这里名字起的不好,或许用DTO表示会更清晰)

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:32:364 * @Version 1.05 * @Description 责任链需要处理的数据6 */

7 @Data8 public classChainEntity {9 //示例字段

10 privateInteger id;11 //示例字段

12 privateString str1;13 //示例字段

14 privateString str2;15 //示例字段

16 private Listquestions;17

18 @Data19 public static classQuestion {20 //示例字段

21 privateLong questionId;22 //示例字段

23 privateString questionName;24 //示例字段

25 private Listanswers;26

27 @Data28 public static classAnswer{29 //示例字段

30 privateLong itemId;31 //示例字段

32 privateString itemContent;33 }34 }35 }

View Code

处理类:RespondChainHandler是一个抽象类,具体的任务处理处理类要继承该类。RespondChainHandler处理类中有两个关键的地方:order和next,order用于加入单向链表时排序使用,next指向的是下一个节点。

调用类:RespondChain,header是单向链表的头节点,processd是任务执行入口,其中参数ChainEntity是外部传入的数据,作为责任链要处理的数据的载体。processd方法从header开始,先执行header节点里的doHandler任务,然后指向next节点,用while循环执行下去,直到没有更多的next节点。

下面我们创建具体的任务子类:

创建保存答题者任务子类:SaveRespondentClient

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:30:224 * @Version 1.05 * @Description 保存答题者任务6 */

7 @Component8 public class SaveRespondentClient extendsRespondChainHandler {9

10 @Override11 protected voiddoHandler(ChainEntity chainEntity) {12 System.out.println("保存答题者任务完成...");13 }14 }

View Code

创建保存答卷任务子类:SaveQuestionnaireClient

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:30:454 * @Version 1.05 * @Description 保存答卷任务6 */

7 @Component8 public class SaveQuestionnaireClient extendsRespondChainHandler {9

10 @Override11 protected voiddoHandler(ChainEntity chainEntity) {12 System.out.println("保存答卷任务完成...");13 }14 }

View Code

创建保存答案任务子类:SaveAnswerClient

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:31:004 * @Version 1.05 * @Description 保存答案任务6 */

7 @Component8 public class SaveAnswerClient extendsRespondChainHandler {9

10 @Override11 protected voiddoHandler(ChainEntity chainEntity) {12 System.out.println("保存答案任务完成...");13 }14 }

View Code

这三个子类处理自己职责范围内的事情。

然后我们创建外部调用类,处理保存答题业务,外部调用类用Controller模拟。我们默认使用的是SpringBoot框架,所以可以不用new对象,使用IOC容器即可。如果不使用SpringBoot当然是可以的,不过要记得将类实例化。

1 /**

2 * @Author Administrator3 * @Date 2021-02-17 15:37:084 * @Version 1.05 * @Description 责任链模式测试controller6 */

7 @RestController8 @RequestMapping("/chain")9 public classChainController {10 //从IOC容器中取出处理类映射成Map,Map的key是处理类的类名,value是已实例化的子类

11 @Resource12 private MaprespondChainHandlerMap;13

14 @GetMapping(value = "save")15 publicString save(){16 ChainEntity chainEntity =newChainEntity();17 RespondChain respondChain = newRespondChain();18 respondChain.addFilter(respondChainHandlerMap.get("saveRespondentClient"), 1);19 respondChain.addFilter(respondChainHandlerMap.get("saveQuestionnaireClient"), 2);20 respondChain.addFilter(respondChainHandlerMap.get("saveAnswerClient"), 3);21 //开始执行

22 respondChain.proceed(chainEntity);23

24 return "执行完成";25 }26 }

View Code

我们启动,测试结果为:

调用成功,任务按照我们的预期依次顺序执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值