首页 > 其他分享 >【代码设计】链表结构解决多流程校验

【代码设计】链表结构解决多流程校验

时间:2023-08-09 11:00:47浏览次数:41  
标签:System 流程 校验 public 链表 println new next void

目的 

使用合理的代码设计,解决业务场景的中的实际问题。

背景介绍 

在实际的业务场景中,用户的一个操作行为,是否允许真正被执行,往往会涉及到多流程的校验,一旦有条件不满足将会被中止。以下面流程图为例:

【代码设计】链表结构解决多流程校验_System

用户点击了打赏按钮,会进行是否有网络检查,没有网络,会有网络连接弹框,等待用户连接结果(涉及异步回调),如果没有连接,不继续下面流程直接结束;如果连接了,会进行是否登录判断,没有登录,则调用引导登录(涉及异步回调),等待登录结果,如果失败,则不继续下面的流程,成功则进行是否是成人账号判断(涉及异步回调),不是则直接结束,是成人账号则真正开始打赏。

根据流程写的代码========

package com.example.quickdemo.node.before;

public class Test {
   public static void main(String[] args) {
      onClickTip();
   }

   /**
    * 点击打赏按钮
    */
   private static void onClickTip() {
      if (!NetworkHelper.getInstance().isConnect()) {
         System.out.println("网络未连接");
         NetworkHelper.getInstance().requestConnectNetwork(new NetworkHelper.NetworkCallback() {
            @Override
            public void onResult(boolean result) {
               if (result) {
                  System.out.println("网络连接成功");
                  if (!LoginHelper.getInstance().isLogin()) {
                     System.out.println("用户未登录");
                     LoginHelper.getInstance().requestLogin(new LoginHelper.LoginCallback() {
                        @Override
                        public void onResult(boolean success) {
                           if (success) {
                              System.out.println("用户登录成功");
                              AccountHelper.getInstance().checkAccountType(new AccountInfo(),
                                 new AccountHelper.AccountCallback() {
                                    @Override
                                    public void onResult(int type) {
                                       if (type == AccountHelper.ACCOUNT_TYPE_ADULT) {
                                          System.out.println("是成人帐号");
                                          doTip();
                                       } else {
                                          System.out.println("不是成人帐号");
                                       }
                                    }
                                 });
                           } else {
                              System.out.println("用户登录失败,结束流程");
                           }
                        }
                     });
                  }
               }
            }
         });
      }
   }

   /**
    * 进行打赏
    */
   public static void doTip() {
      System.out.println("通过了一系列合法性校验,可以进行打赏");
   }
}

会明显的发现,代码实现上陷入了回调地狱,即在回调中右进行了不断的回调,直接表现在会出现多层的代码缩进,回调地狱往往会使代码的易读性大大的降低,各个校验的耦合性大大增强。

下面是各个网络、登录,账号校验的实现代码,仅仅辅助示例说明,并不是真正的连接网络,进行登录,帐号校验的实现

package com.example.quickdemo.node.before;

/**
 * 网络辅助类
 */
public class NetworkHelper {
   private boolean connect;

   private static final NetworkHelper INSTANCE = new NetworkHelper();

   private NetworkHelper() {
   }

   public static NetworkHelper getInstance() {
      return INSTANCE;
   }

   public boolean isConnect() {
      return connect;
   }

   public void setConnect(boolean connect) {
      this.connect = connect;
   }

   public void requestConnectNetwork(final NetworkCallback callback) {
      new Thread(new Runnable() {
         @Override
         public void run() {
            try {
               Thread.sleep(500);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
            connect = true;
            if (callback != null) {
               callback.onResult(connect);
            }
         }
      }).start();
   }

   interface NetworkCallback {
      void onResult(boolean result);
   }
}
package com.example.quickdemo.node.before;

/**
 * 登录辅助类
 */
public class LoginHelper {
   private boolean isLogin;


   private static final LoginHelper INSTANCE = new LoginHelper();

   private LoginHelper() {
   }

   public static LoginHelper getInstance() {
      return INSTANCE;
   }

   public boolean isLogin() {
      return isLogin;
   }

   public void requestLogin(final LoginCallback callback) {
      new Thread(new Runnable() {
         @Override
         public void run() {
            try {
               Thread.sleep(500);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
            isLogin = true;
            if (callback != null) {
               callback.onResult(isLogin);
            }
         }
      }).start();
   }


   interface LoginCallback {
      void onResult(boolean success);
   }
}
package com.example.quickdemo.node.before;

/**
 * 帐号辅助类
 */
public class AccountHelper {
   public static final int ACCOUNT_TYPE_ADULT = 1;

   private static final AccountHelper INSTANCE = new AccountHelper();

   private AccountHelper() {
   }

   public static AccountHelper getInstance() {
      return INSTANCE;
   }

   public void checkAccountType(AccountInfo accountInfo, final AccountCallback callback) {
      new Thread(new Runnable() {
         @Override
         public void run() {
            try {
               Thread.sleep(500);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
            if (callback != null) {
               callback.onResult(ACCOUNT_TYPE_ADULT);
            }
         }
      }).start();
   }

   interface AccountCallback {
      void onResult(int type);
   }
}

使用链表结构解决回调地狱============

每一种校验可以看做是链表的一个节点,进行当前节点的校验时,如果校验不成功则不继续进行,如果校验成功,则判断是否有下一个节点,如果有则执行下一个节点。

在开始执行链表的逻辑之前,首先需要构建出一个链表,而链表节点的先后顺序就是多流程校验各流程的顺序。

首先定义结点

package com.example.quickdemo.node.after;

public abstract class FlowNode {
    private FlowNode next;

    /**
     * 事务处理
     */
    public abstract void process();

    public FlowNode getNext() {
        return next;
    }

    public void setNext(FlowNode next) {
        this.next = next;
    }
}

创建网络、登录,账号校验各自的结点实现

package com.example.quickdemo.node.after;

import com.example.quickdemo.node.before.NetworkHelper;

/**
 * 网络结点
 */
public class NetworkFlowNode extends FlowNode{
    @Override
    public void process() {
        if (NetworkHelper.getInstance().isConnect()) {
            System.out.println("网络已连接");
            FlowNode next = getNext();
            if (next != null) {
                next.process();
            }
        } else {
            System.out.println("网络未连接");
            NetworkHelper.getInstance().requestConnectNetwork(new NetworkHelper.NetworkCallback() {
                @Override
                public void onResult(boolean result) {
                    if (result) {
                        System.out.println("网络连接成功");
                        FlowNode next = getNext();
                        if (next != null) {
                            next.process();
                        }
                    } else {
                        System.out.println("用户登录失败,结束流程");
                    }
                }
            });
        }
    }
}
package com.example.quickdemo.node.after;

import com.example.quickdemo.node.before.LoginHelper;

/**
 * 登录结点
 */
public class LoginFlowNode extends FlowNode{
    @Override
    public void process() {
        if (LoginHelper.getInstance().isLogin()) {
            System.out.println("用户已登录");
            FlowNode next = getNext();
            if (next != null) {
                next.process();
            }
        } else {
            System.out.println("用户未登录");
            LoginHelper.getInstance().requestLogin(new LoginHelper.LoginCallback() {
                @Override
                public void onResult(boolean success) {
                    if (success) {
                        System.out.println("用户登录成功");
                        FlowNode next = getNext();
                        if (next != null) {
                            next.process();
                        }
                    } else {
                        System.out.println("用户登录失败,结束流程");
                    }
                }
            });
        }
    }
}
package com.example.quickdemo.node.after;

import com.example.quickdemo.node.before.AccountHelper;
import com.example.quickdemo.node.before.AccountInfo;

/**
 * 账号校验结点
 */
public class AdultAccountFlowNode extends FlowNode {
    @Override
    public void process() {
        AccountHelper.getInstance().checkAccountType(new AccountInfo(), new AccountHelper.AccountCallback() {
            @Override
            public void onResult(int type) {
                if (type == AccountHelper.ACCOUNT_TYPE_ADULT) {
                    System.out.println("是成人帐号");
                    FlowNode next = getNext();
                    if (next != null) {
                        next.process();
                    }
                } else {
                    System.out.println("不是成人帐号,结束流程");
                }
            }
        });
    }
}

打赏服务,进行打赏业务时,进行了链表的构建,类似于搭积木,各个校验模块之间已经没有直接的耦合关系。

package com.example.quickdemo.node.after;

/**
 * 打赏服务
 */
public class TipService extends FlowNode{

    public void onClickTip() {
        // 构建校验链表
        // (1) 创建结点
        NetworkFlowNode networkFlowNode = new NetworkFlowNode();
        LoginFlowNode loginFlowNode = new LoginFlowNode();
        AdultAccountFlowNode adultAccountFlowNode = new AdultAccountFlowNode();
        // (2)根据校验顺序连接结点
        networkFlowNode.setNext(loginFlowNode);
        loginFlowNode.setNext(adultAccountFlowNode);
        adultAccountFlowNode.setNext(this);

        // 触发链表调用
        networkFlowNode.process();
    }

    @Override
    public void process() {
        doTip();
    }

    /**
     * 进行打赏
     */
    public void doTip() {
        System.out.println("通过了一系列合法性校验,可以进行打赏");
    }
}

调用测试

package com.example.quickdemo.node.after;

public class Test {
    public static void main(String[] args) {
        new TipService().onClickTip();
    }
}

输出

网络未连接
网络连接成功
用户未登录
用户登录成功
是成人帐号
通过了一系列合法性校验,可以进行打赏

如果进行登录引导时,用户不进行登录直接返回,即引导登录流程返回失败,输出将是:

网络未连接
网络连接成功
用户未登录
用户登录失败,结束流程

总结==

针对具体的业务场景,设计出相适应的代码设计,才能够更好的演进。本文介绍的方案其实和设计模式中的责任链模式比较类似,责任链本质也是一个链表,只是其处理大致逻辑是,当前结点如果能够处理请求,则直接处理,然后结束,如果不能够处理,则交给下一个结点处理。

在一些框架中,如RxJava,Kotlin的协程,前端的Promise都是可以用来解决多流程校验,存在回调地狱的场景。提到的框架没有仔细深入的了解过,不敢讲太多~

想要了解更多Anrloid相关知识可以点击下方课堂链接                https://edu.51cto.com/course/32703.html Android课

标签:System,流程,校验,public,链表,println,new,next,void
From: https://blog.51cto.com/u_16163480/7016862

相关文章

  • 格律诗乐器的生产流程和质量控制
    格律诗乐器的生产流程和质量控制格律诗乐器是一种传统而独特的中国乐器,它在音色、音质和外观上都有着高要求。为了制造出具有优秀品质的格律诗乐器,需要经过一系列严格的生产流程和质量控制步骤。一、原材料采购和质量评估格律诗乐器的制作过程始于原材料的采购。制作格律诗乐器......
  • @Constraint注解,做特殊的入参校验
    //@Constraint是Java中的注解之一,用于标记自定义的约束注解。约束注解通常用于数据验证,用来限制字段的取值或格式,确保数据的合法性。@Constraint(validatedBy=FlagValidate.class) 第一步:先建一个@interfaceFlag的注解校验类,注解相关的校验类为FlagValidate.Class:im......
  • 格律诗乐器的生产流程和质量控制流程说明
    一、格律诗乐器说明格律诗乐器是一种独特的音乐器乐,广泛用于传统音乐演奏和文化活动中。在制作格律诗乐器时,生产流程和质量控制是非常重要的环节。本文将详细介绍格律诗乐器的生产流程和质量控制流程,以确保乐器的制作质量和音乐效果的卓越性。二、格律诗乐器的生产流程格律诗乐......
  • 格律诗乐器的生产流程和质量控制流程
    格律诗乐器是一种独特而富有传统韵味的乐器,它在音乐界有着广泛的影响力。制造格律诗乐器需要经历一系列复杂的生产流程和严格的质量控制标准。本文将详细介绍格律诗乐器的生产流程和质量控制流程,以帮助读者更好地了解该乐器的制造过程和质量保障。首先,格律诗乐器的制造过程中,原材......
  • MySQL流程控制语句
    连接数据库mysql-hlocalhost-uroot-prootMySQL函数函数:是指一段可以直接被另一段程序调用的程序或代码。在MySQL中会有很多的内置函数,我们只需要使用就行;常见的字符串函数concat函数selectconcat('hello','zhangsan');返回的是:hellozhangsanselectlower('HELLo......
  • 《天道》--格律诗乐器的生产流程和质量控制
    最近几天,我在王建民老师的建议下观看了王志文老师主演的电视剧《天道》。在看完第一集之后,我发现这个剧情非常有趣,于是我决定耐心地看完整个剧集。看完之后,我仿佛开启了一片新的天地,这部剧简直是个神作。看完之后,我有了很多感悟和思考,让我体验到了许多新鲜的思维。接下来,我将简单......
  • 对于《天道》电视剧当中格律诗乐器的制作流程和质量控制流程的说明
    近期我在建民老师的指引下观看了《天道》这一电视剧,在剧中格律诗乐器的生产是在家庭里进行,牺牲生活环境和时间,利用廉价劳动力来降低成本,就可以降价竞争,对此我也产生了一些感想。在家庭里进行格律诗乐器生产,虽然需要牺牲生活环境和时间,利用廉价劳动力来降低成本,以便降价竞争,但在这......
  • 递归反转链表局部[labuladong-刷题打卡 day8]
    写在前面前两天刷题打卡,感觉东哥的代码模板没有题解中的简洁,或者那些极限优化的代码中有很多优化技巧,但今天去感受递归的含义的时候,觉得毕竟我现在是在学习算法,理解算法含义才是学习的意义。至于优化,那是之后的事,所以刷题的时候不必过于追求简洁,就像追求简洁而降低可读性一样属......
  • vue3 + h5 构建流程
    目录目录初始化项目架构技术栈工具类环境搭建流程初始化项目初始化git运行项目配置server环境vite.config.ts配置项目环境增加三个文件修改package.json脚本如何使用重新启动配置Eslint增加文件.eslintrc.cjs对vite.config.ts修改重新启动......
  • 处理器核心 错误源: 已更正的计算机检查 错误类型: 内部奇偶校验错误
    问题描述:最近工作用的PC,会偶发的自动重启问题原因:起初以为是CPU过热(毕竟是过40度的城市),然而经过一系列的检查并未发现风扇异常。想着这台PC也跟了我快3年了,估计积灰可能比较严重,于是清理了一下,结果仍然没有解决最终,在事件查看器->系统中看到在自动重启前系统记录了一条错误日志“......