美文网首页大后端
if else看腻了,能换种玩法吗?

if else看腻了,能换种玩法吗?

作者: 凯凯雄雄 | 来源:发表于2020-12-11 19:43 被阅读0次

平常在公司看到很多业务逻辑的代码可能就是if/else各种判断,虽然也有一些设计模式能够解决一些问题,但是感觉都不是特别好用。刚好这次有个场景比较符合这个命题来聊一下如何去实践的.

先说一下场景吧:
目前有些场景需要基于BinLog的变化去做一些业务变更操作,比如有

  1. 一些表字段中冗余了各种名称,希望这些源表发生变更的时候,能够顺带更新冗余字段表中的值。
  2. 随着一些表的数据越来越大,一些表关联让SQL越来越慢,目前是希望压缩数据,所以数据发生变化了需要实时通知某些业务。
  3. 还有一些最终一致性的业务

基于阿里云DTS封装成Spring的应用

目前已经将Binlog发送到消息队列存储好了,表名为Tag,开发根据自己关注的表名指定好,然后去处理特定的逻辑

消费者:
伪代码 :


public class BinlogConsumer{
    public void consumer(TableInfo table){
        String tableName = table.getTableName();
        if(request.equals("TB_A")){
            // 处理A表变更后的业务逻辑
        }else if(request.equals("TB_B")){
            // 处理B表变更后的逻辑
        }else if(request.equals("TB_C")){
            // 处理C表变更后的逻辑
        }else if(request.equals("TB_D")){
            // 处理D表变更后的逻辑
        }
    }
}

随着业务要处理的表越来越多,会发现判断也会越来越多。
如果每个变更业务逻辑的方法抽象成小的方法还好,最怕的就是有的开发拿着就是一把梭,所有逻辑全部怼到一个方法!!!

我已经遇到过太多了!太辛苦了。

目前对于这种场景的话一开始制定好规范,让其他开发按照同样的套路去做的话会省力一点。

通过JDK8的Function编程去实现:

方法1

import org.springframework.util.Assert;
import java.util.function.Consumer;
/**
 * @Module 执行器
 * @Description 等值比较处理
 * @Author liukaixiong
 * @Date 2020/12/11 15:48
 */
public interface EqualsValueInvoke<T> {
    /**
     * 等值比较执行方法
     *
     * @param eqA      值A
     * @param eqB      值B
     * @param req      请求参数
     * @param consumer 具体的执行方法
     * @return
     */
    default void invoke(String eqA, String eqB, T req, Consumer<T> consumer) {

        Assert.notNull(eqA, "eqA is not null");
        Assert.notNull(eqB, "eqB is not null");

        if (eqA.equals(eqB)) {
            consumer.accept(req);
        }
    }
}

使用的测试用例:

public class EqualsValueInvokeTest extends TestCase implements EqualsValueInvoke<String> {
     @Test
    public void testInvoke() {
        String request = "Table_B";
        // 在这个方法内可以根据特定的表找对应的处理方法
        invoke(request, "Table_A", request, this::processTableA);
        invoke(request, "Table_B", request, this::processTableB);
    }

    public void processTableA(String req) {
        String s = "processTableA_" + req;
        System.out.println(s);
    }

    public void processTableB(String req) {
        String s = "processTableA_" + req;
        System.out.println(s);
    }
}

看上去会稍微清晰一点,当然实际上还是if、else的写法。

方法2

在方法1的基础上在升级一下,利用注解来标明关注的TableName,Map来存储关系

import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Module 处理器
 * @Description 等值处理器
 * @Author liukaixiong
 * @Date 2020/12/11 14:38
 */
public interface EqualsValueProcess<T> extends InitializingBean {

    Map<String, Method> equalsMap = new HashMap<String, Method>();

    @Override
    default void afterPropertiesSet() throws Exception {
        Method[] methods = this.getClass().getMethods();
        Arrays.stream(methods).filter((t) -> {
            return t.getAnnotation(RequestMapping.class) != null;
        }).forEach((method) -> {
            RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
            String value = requestMapping.value()[0];
            equalsMap.put(value, method);
        });
    }

    default void process(Object obj, String key, T request) throws Exception {
        Method method = equalsMap.get(key);
        if (method != null) {
            method.invoke(obj, request);
        } else {
            System.out.println("找不到匹配的值:" + key);
        }
    }
}

测试用例:



import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Module TODO
 * @Description TODO
 * @Author liukaixiong
 * @Date 2020/12/11 15:19
 */
@RunWith(JUnit4.class)
public class EqualsValueProcessTest implements EqualsValueProcess<String> {
    // 假设这是Binlog传递过来的参数
    private String defaultTable = "Table_A";

    @Before
    public void init() throws Exception {
        afterPropertiesSet();
    }

    @Test
    public void testProcess() throws Exception {
        process(this, defaultTable, "你好");
    }
    
    @RequestMapping(value = "Table_A")
    public void methodA(String param) {
        System.out.println(param + "\t A");
    }

    @RequestMapping(value = "Table_B")
    public void methodC(String param) {
        System.out.println(param + "\t B");
    }
}

当然这里只是做测试(用的是SpringMVC的@RequestMapping),可以根据许多场景去制定注解的规则,比一定非得是等值比较。
这样的实现的话,就会将对应的值根据注解路由到特定的方法。

可能是使用起来比较习惯的方式。

第一种方式的话,读起来感觉会更清晰一点,所有表名旁边就是对应的处理逻辑方法,性能比第二种要好。

第二种方式的话:使用起来会更方便,直接告诉注解你需要那张表的数据,用惯了Spring的会更贴切。

其实根据这些思路还可以衍生其他方法,定义好规范的话,统一管理对大家都好。

相关文章

  • if else看腻了,能换种玩法吗?

    平常在公司看到很多业务逻辑的代码可能就是if/else各种判断,虽然也有一些设计模式能够解决一些问题,但是感觉都不...

  • 2018-07-31

    while。。。 else。。。的玩法

  • 【坚持画画第88天】打卡了。。

    换种玩法啦~昨晚的,嘿

  • 刺绣花朵

    许久没刺绣了,手都有些生了。跟一群手工人约着做一个小包,原计划贴布的,最近贴布玩腻了,换种玩法,刺绣。 描图后就开...

  • 头像腻了,换一换?

    这个功能一推出,手绘插画师就很郁闷了,哎!

  • 墙面刷上蓝色漆,家里美丽又安静

    知道吗,墙面装修做的好,整个家的颜值都能获得提升,如果你看腻了自家的大白墙,正想换一换墙面,不妨换一换墙面颜色。 ...

  • 换种玩法,拥有喜乐

    大多数人都玩过“抢椅子”的游戏,这是淘汰制玩法:板凳比人数少一,指令结束后能坐到板凳上的游戏者获得游戏资格,得以继...

  • 8086汇编三——反汇编03:switch case 和 if

    一、if else if else 就是比较。 二、switch case 以空间换时间,来提高效率。若空间相差太...

  • 角色能换吗

    曾有那么一段时间 热衷于赚钱 赚钱就买买买 那个开心啊 后来突然泄气了 觉得没意思没动力…… 如果一直坚持下来 想...

  • 关于纸巾的想象

    昨天给小妞洗澡,她非要拿一张湿纸巾放进洗澡盆玩水,平时是拿一个玩具捞水玩,可能玩腻了想换一下玩法。我没有反对她,让...

网友评论

    本文标题:if else看腻了,能换种玩法吗?

    本文链接:https://www.haomeiwen.com/subject/wyksgktx.html