• (1)设计模式之责任链模式


    目录

    一、定义 

    二、使用场景

    三、代码示例

    1. 示例场景-闯关游戏:

    2. 思路分析:

    3. 责任链模式的基本组成:

    4. 代码示例

    四、真实业务中的改造


    一、定义 

    将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
    以上定义来自《设计模式之美》

    二、使用场景

    • 多条件流程判断:权限控制

    • ERP 系统流程审批:总经理、人事经理、项目经理

    • Java 过滤器的底层实现 Filter

    三、代码示例

    1. 示例场景-闯关游戏:

    • 游戏一共 3 个关卡

    • 进入第二关需要第一关的游戏得分大于等于 70

    • 进入第三关需要第二关的游戏得分大于等于 90

    2. 思路分析:

    思考:每个关卡中都有下一关的成员变量,并且是不一样的,那么我们可以在关卡上抽象出一个父类或者接口,然后每个具体的关卡去继承或者实现。

    3. 责任链模式的基本组成:

    • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

    • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

    • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

    4. 代码示例

    抽象类:

    1. /**
    2. * 责任链模式--抽象处理者角色
    3. *
    4. */
    5. public abstract class AbstractHandler {
    6. /**
    7. * 下一关用当前抽象类来接收
    8. */
    9. protected AbstractHandler next;
    10. public void setNext(AbstractHandler next) {
    11. this.next = next;
    12. }
    13. public abstract int handler();
    14. }

     链条上的各节点:

    1. // 编写具体的处理器来继承AbstractHandler类
    2. public class FirstPassHandler extends AbstractHandler {
    3. private int play() {
    4. return 80;
    5. }
    6. @Override
    7. public int handler() {
    8. System.out.println("第一关: FirstPassHandler.handler()");
    9. int score = play();
    10. if (score >= 70) {
    11. // 有下一关
    12. if (this.next != null) {
    13. return this.next.handler();
    14. }
    15. }
    16. return score;
    17. }
    18. }
    19. public class SecondPassHandler extends AbstractHandler {
    20. private int play() {
    21. return 90;
    22. }
    23. @Override
    24. public int handler() {
    25. System.out.println("第二关: SecondPassHandler.handler()");
    26. int score = play();
    27. if (score >= 90) {
    28. // 有下一关
    29. if (this.next != null) {
    30. return this.next.handler();
    31. }
    32. }
    33. return score;
    34. }
    35. }
    36. public class ThirdPassHandler extends AbstractHandler {
    37. private int play() {
    38. return 95;
    39. }
    40. @Override
    41. public int handler() {
    42. System.out.println("第三关: ThirdPassHandler.handler()");
    43. int score = play();
    44. if (score >= 95) {
    45. // 有下一关
    46. if (this.next != null) {
    47. return this.next.handler();
    48. }
    49. }
    50. return score;
    51. }
    52. }

    客户端处理:

    1. public class ChainHandlerClient {
    2. public static void main(String[] args) {
    3. // 第一关
    4. FirstPassHandler firstPassHandler = new FirstPassHandler();
    5. // 第二关
    6. SecondPassHandler secondPassHandler = new SecondPassHandler();
    7. // 第三关
    8. ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
    9. firstPassHandler.setNext(secondPassHandler);
    10. secondPassHandler.setNext(thirdPassHandler);
    11. // 从第一个关卡开始
    12. firstPassHandler.handler();
    13. }
    14. }

    运行结果:

    四、真实业务中的改造

    框架中的这种思想,应用于真实业务中时就对应一些修改

    举一个例子:

    订单详情页中有很多模块,比如:地址模块、商品详情模块...

    1. @Data
    2. public class ItemInfo {
    3. private Long itemId;
    4. private String itemName;
    5. }
    6. @Data
    7. public class SkuInfo {
    8. private Long skuId;
    9. private String skuName;
    10. }
    1. // 抽象方法
    2. public abstract class AbstractDataHandler<T> {
    3. protected abstract T doRequest(String query);
    4. }
    1. // 实现类
    2. @Component
    3. public class AddressInfoHandler extends AbstractDataHandler<ItemInfo> {
    4. @Override
    5. protected ItemInfo doRequest(String query) {
    6. ItemInfo info = new ItemInfo();
    7. info.setItemId(898989L);
    8. info.setItemName("测试商品");
    9. return info;
    10. }
    11. }
    12. @Component
    13. public class SkuInfoHandler extends AbstractDataHandler<SkuInfo> {
    14. @Override
    15. protected SkuInfo doRequest(String query) {
    16. SkuInfo info = new SkuInfo();
    17. info.setSkuId(12121212L);
    18. info.setSkuName("测试SKU");
    19. return info;
    20. }
    21. }
    1. // 测试类
    2. @RestController
    3. public class ChainController {
    4. @Autowired
    5. private SkuInfoHandler skuInfoHandler;
    6. @Autowired
    7. private AddressInfoHandler itemInfoHandler;
    8. @RequestMapping("/query")
    9. public Map convertItemDetail() {
    10. Map result = new HashMap();
    11. result.put("skuInfoHandler", skuInfoHandler.doRequest("模拟数据请求"));
    12. result.put("itemInfoHandler", itemInfoHandler.doRequest("模拟数据请求"));
    13. System.out.println(JSON.toJSONString(result));
    14. return result;
    15. }
    16. }

    执行结果:

    1. {
    2. "skuInfoHandler":{
    3. "skuId":12121212,
    4. "skuName":"测试SKU"
    5. },
    6. "itemInfoHandler":{
    7. "itemId":898989,
    8. "itemName":"测试商品"
    9. }
    10. }

    大家应该看出这其中的不一样了,这个例子中,我们并没有将handler向下传递,而是通过convertItemDetail方法将各模块封装起来,组成一个map返回。

    实际开发中,我们要根据不同业务场景将某些设计模式做适配。

  • 相关阅读:
    java毕业设计全套基于SSM的垃圾分类管理系统
    windows mysql5.7 开启binlog日志
    肝癌来时“静悄悄”?早期肝癌为什么不会痛?一文读懂→
    【Java】BMI身体质量指数计算工具
    JWT——讲解
    【优化充电】基于matlab粒子群算法电动汽车充电动态优化策略【含Matlab源码 2163期】
    在家怎么做芋圆 芋圆的做法
    Nvidia 硬件架构
    【Kotlin】初识Kotlin(二)
    C语言深入学习 --- 7.程序的编译
  • 原文地址:https://blog.csdn.net/weixin_40618648/article/details/125336925