干掉 if 语句,一个不留的那种!

2023-12-15 06:08
文章标签 干掉 语句 那种 不留

本文主要是介绍干掉 if 语句,一个不留的那种!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达今日推荐:推荐19个github超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多

 作者:乌塔卡

juejin.cn/post/6951764927958745124

业务场景

近日在公司领到一个小需求,需要对之前已有的试用用户申请规则进行拓展。我们的场景大概如下所示:

if (是否海外用户) {return false;
}if (刷单用户) {return false;
}if (未付费用户 && 不再服务时段) {return false
}if (转介绍用户 || 付费用户 || 内推用户) {return true;
}

按照上述的条件我们可以得出的结论是:

  • 咱们的的主要流程主要是基于 and 或者 or 的关系。

  • 如果有一个不匹配的话,其实咱们后续的流程是不用执行的,就是需要具备一个短路的功能。

  • 对于目前的现状来说,我如果在原有的基础上来改,只要稍微注意一下解决需求不是很大的问题,但是说后面可维护性非常差。

后面进过权衡过后,我还是决定将这个部分进行重构一下。

规则执行器

针对这个需求,我首先梳理了一下咱们规则执行器大概的设计, 然后我设计了一个 V1 版本和大家一起分享一下,如果大家也有这样的 case 可以给我分享留言,下面部分主要是设计和实现的流程和 code.

规则执行器的设计

对于规则的抽象并实现规则

// 业务数据
@Data
public class RuleDto {private String address;private int age;
}// 规则抽象
public interface BaseRule {boolean execute(RuleDto dto);
}// 规则模板
public abstract class AbstractRule implements BaseRule {protected <T> T convert(RuleDto dto) {return (T) dto;}@Overridepublic boolean execute(RuleDto dto) {return executeRule(convert(dto));}protected <T> boolean executeRule(T t) {return true;}
}// 具体规则- 例子1
public class AddressRule extends AbstractRule {@Overridepublic boolean execute(RuleDto dto) {System.out.println("AddressRule invoke!");if (dto.getAddress().startsWith(MATCH_ADDRESS_START)) {return true;}return false;}
}// 具体规则- 例子2
public class NationalityRule extends AbstractRule {@Overrideprotected <T> T convert(RuleDto dto) {NationalityRuleDto nationalityRuleDto = new NationalityRuleDto();if (dto.getAddress().startsWith(MATCH_ADDRESS_START)) {nationalityRuleDto.setNationality(MATCH_NATIONALITY_START);}return (T) nationalityRuleDto;}@Overrideprotected <T> boolean executeRule(T t) {System.out.println("NationalityRule invoke!");NationalityRuleDto nationalityRuleDto = (NationalityRuleDto) t;if (nationalityRuleDto.getNationality().startsWith(MATCH_NATIONALITY_START)) {return true;}return false;}
}// 常量定义
public class RuleConstant {public static final String MATCH_ADDRESS_START= "北京";public static final String MATCH_NATIONALITY_START= "中国";
}

执行器构建

public class RuleService {private Map<Integer, List<BaseRule>> hashMap = new HashMap<>();private static final int AND = 1;private static final int OR = 0;public static RuleService create() {return new RuleService();}public RuleService and(List<BaseRule> ruleList) {hashMap.put(AND, ruleList);return this;}public RuleService or(List<BaseRule> ruleList) {hashMap.put(OR, ruleList);return this;}public boolean execute(RuleDto dto) {for (Map.Entry<Integer, List<BaseRule>> item : hashMap.entrySet()) {List<BaseRule> ruleList = item.getValue();switch (item.getKey()) {case AND:// 如果是 and 关系,同步执行System.out.println("execute key = " + 1);if (!and(dto, ruleList)) {return false;}break;case OR:// 如果是 or 关系,并行执行System.out.println("execute key = " + 0);if (!or(dto, ruleList)) {return false;}break;default:break;}}return true;}private boolean and(RuleDto dto, List<BaseRule> ruleList) {for (BaseRule rule : ruleList) {boolean execute = rule.execute(dto);if (!execute) {// and 关系匹配失败一次,返回 falsereturn false;}}// and 关系全部匹配成功,返回 truereturn true;}private boolean or(RuleDto dto, List<BaseRule> ruleList) {for (BaseRule rule : ruleList) {boolean execute = rule.execute(dto);if (execute) {// or 关系匹配到一个就返回 truereturn true;}}// or 关系一个都匹配不到就返回 falsereturn false;}
}

执行器的调用

public class RuleServiceTest {@org.junit.Testpublic void execute() {//规则执行器//优点:比较简单,每个规则可以独立,将规则,数据,执行器拆分出来,调用方比较规整//缺点:数据依赖公共传输对象 dto//1. 定义规则  init ruleAgeRule ageRule = new AgeRule();NameRule nameRule = new NameRule();NationalityRule nationalityRule = new NationalityRule();AddressRule addressRule = new AddressRule();SubjectRule subjectRule = new SubjectRule();//2. 构造需要的数据 create dtoRuleDto dto = new RuleDto();dto.setAge(5);dto.setName("张三");dto.setAddress("北京");dto.setSubject("数学");;//3. 通过以链式调用构建和执行 rule executeboolean ruleResult = RuleService.create().and(Arrays.asList(nationalityRule, nameRule, addressRule)).or(Arrays.asList(ageRule, subjectRule)).execute(dto);System.out.println("this student rule execute result :" + ruleResult);}
}

总结

规则执行器的优点和缺点

优点:

  • 比较简单,每个规则可以独立,将规则,数据,执行器拆分出来,调用方比较规整;

  • 我在 Rule 模板类中定义 convert 方法做参数的转换这样可以能够,为特定 rule 需要的场景数据提供拓展。

缺点:

  • 上下 rule 有数据依赖性,如果直接修改公共传输对象 dto 这样设计不是很合理,建议提前构建数据。

推荐文章
  • 2021 最新版 Spring Boot 速记教程

  • 2W 字你全面认识 Nginx

  • 47K Star 的SpringBoot+MyBatis+docker电商项目,附带超详细的文档!

  • 写博客能月入10K?

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

更多项目源码
  • 这或许是最美的Vue+Element开源后台管理UI

  • 推荐一款高颜值的 Spring Boot 快速开发框架

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

  • 13K点赞都基于 Vue+Spring 前后端分离管理系统ELAdmin,大爱

  • 想接私活时薪再翻一倍,建议根据这几个开源的SpringBoot项目

这篇关于干掉 if 语句,一个不留的那种!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/495376

相关文章

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库

FPGA开发:条件语句 × 循环语句

条件语句 if_else语句 if_else语句,用来判断是否满足所给定的条件,根据判断的结果(真或假)决定执行给出的两种操作之一。 if(表达式)语句; 例如: if(a>b) out1=int1; if(表达式)         语句1; else         语句2; 例如: if(a>b)out1=int1;elseout1=int2; if(表达式1) 语句1; els

mysql 修改表结构语句

主要还是要参考mysql的官方网站 http://dev.mysql.com/doc/refman/5.7/en/alter-table.html 简单例子: alter table_name alter column old_column_name new_column_name int unsigned;

MySQL学习笔记-join语句类型

join从句的类型:内链接(inner) 全外连接(full outer) 左外连接(left outer) 右外连接(right outer) 交叉链接(cross) 连接条件:使用ON设定连接条件,也可以用WHERE代替 · ON:设定连接条件 · WHERE:进行结果集记录的过滤 一,内连接inner join:  内连接是返回左表及右表符合连接条件的记录,在MySQL中JO

Oracle和Sql_Server 部分sql语句的区别

比如:A表中, 字段:gxmlflag  number;  比如数据:20210115 字段:gxmldate date ;    比如数据:2021-01-15 09:50:50 一、在Oracle数据库中: 1、insert 和 update 语句: t.gxmlflag = to_char(sysdate,'yyyymmdd'),t.gxmldate=sysdate 比如:update f

PostgreSql中WITH语句的使用

https://blog.csdn.net/chuan_day/article/details/44809125 PostgreSql中WITH语句的使用 With语句是为庞大的查询语句提供了辅助的功能。这些语句通常是引用了表表达式或者CTEs(一种临时数据的存储方式),可以看做是一个查询语句的临时表。在With语句中可以使用select,insert,update,delete语句。当然wit

【语句】如何将列表拼接成字符串并截取20个字符后面的

base_info = "".join(tree.xpath('/html/head/script[4]/text()'))[20:] 以下是对这个语句的详细讲解: tree.xpath('/html/head/script[4]/text()')部分: tree:通常是一个已经构建好的 HTML 文档树对象,它是通过相关的 HTML 解析库(比如 lxml)对 HTML 文档进行解

Shell脚本判断、if语句

1、条件测试类型 整数测试 字符测试 文件测试 2、条件测试的表达式 [ 条件表达式 ][[ 条件表达式 ]]test 条件表达式 示例: [root@node1 ~]# test -e file && echo true || echo false # 测试是否又file这个文件false [root@node1 ~]# touch file

SQL SELECT常用语句

SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL)。 SQL (结构化查询语言)是用于执行查询的语法。但是 SQL 语言也包含用于更新、插入和删除记录的语法。 查询和更新指令构成了 SQL 的 DML 部分: •SELECT - 从数据库表中获取数据 •UPDATE - 更新数据库表中的数据 •DELETE - 从数