如何优化IF/ESE的结构

目前总结了三种简化多层 if/else 的方法:

  1. 多态的方式。
  2. 图结构解决
  3. 判断树
  4. 反射机制

多态方式。

多态的方式利用 Java 对象多态的特性。如下所示样式的语句。

public void method(flag){

    if(flag == var1){
        //do_something
    }else if(flag == varr){
        // do_something
    }else{
        // the last choice
    }

}

我们可以改造成如下的写法;

public void method(flag){
    AInterface inter = map.get(flag);
    inter.handler(data);
}

我们先建一个接口,在接口中定义处理数据的方法名称。
再实现对应每种 flag 的类。然后,将类放到 map 里面。
这样得代码是不是看起来简洁了许多。

还可以使用枚举来实现。

public Enur{
    ONE(1){
        public void handler(JavaBean jb){
            // 1 对应的处理方法。
        }
    };
    TWO(2){
        public void handler(JavaBean jb){
            // 2 对应的处理方法。
        }
    }
    public int type ;
    public void handler(JavaBean jb);
}

EnurMap 对 type 值进行检索就 ok 了。

如果是多个判断条件,就需要构建一颗判断树。举个例子,如果有 10 个参数,如果第一个参数逻辑判断结果是 true ,则对第二个参数进行逻辑判断,否则使用第三个参数进行逻辑判断。依次类推。这种一环扣着一环,层层递进的模式,像不像一颗树。

判断树

先来定义一个接口,这个接口规定了判断树走向的方法、对数据的处理方法。

abstract class ConditionTree<T>{
    // 根据 JavaBean 成员变量中的值,进行判断
    // 最后返回真或真假。
    // return 判断结果 ;
    public abstract ConditionTree ConditionExec(JavaBean jb);
    public abstract ConditionTree left ;
    public abstract ConditionTree right;
    public abstract T dataHandler(JavaBean jb){
        // 对 JavaBean 惊醒处理。这里也可以是一个数组。
        // 然后,最后返回一个 T 。
    }
}

然后我们就可以在类里面实现我们的判断逻辑了。例如:

public class Field1 implements ConditionTree<Result> {
    public ConditionTree ConditionExec(JavaBean jb){
        if(jb.getField1() > 1){
            return new Field2(jb);
        }

        return this ;
    }
    public void setLeft(ConditionTree ct){
        this.left = ct ;
    }
    public void setRight(ConditionTree ct){
        this.right = ct ;
    }
    public Result dataHandler(JavaBean jb){
        // 对 jb 做处理
    }
}

如果我们用图来表示这样的结果,就得到如下图表。

                node
                /    \
            node      node
           /   \     /    \
        node  node  node   node

当走到一个叶子节点的时候,就需要调用 dataHandler 方法,返回 Result。

反射机制

这个机制在 MVC 中的 Controller 应用的非常多。例如,Spring 的 MVC ,经常会定义如下的东西。

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    // 显示用户列表页面
    @GetMapping("/users")
    public String showUserList(Model model) {
        List<User> userList = userService.getAllUsers();
        model.addAttribute("users", userList);
        return "user-list";
    }

    // 显示添加用户页面
    @GetMapping("/users/add")
    public String showAddUserForm(Model model) {
        model.addAttribute("user", new User());
        return "add-user";
    }
}

当我们在浏览器输入不同的路径后,Spring 会帮我们根据路径转入到不同的方法发里面。

关键的代码如下所示:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface GetMapping {
    String tag() default "default" ;
}

然后,然后使用 Spring 再根据反射的机制,保存一份 <tag ,Method> 的对应关系。

import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) {
        try {
            // 获取 UserController 类的 Class 对象
            Class<?> controllerClass = Class.forName("com.example.UserController");
            
            // 创建 UserController 的实例
            Object controller = controllerClass.newInstance();
            Map<String, Method> keyMethod = new HashMap<>();
          for (Method method : controllerClass.getClass().getDeclaredMethods()) {
            if(method.isAnnotationPresent(GetMapping.class)){
                GetMapping annotation = method.getAnnotation(GetMapping.class);
                method.setAccessible(true);
                keyMethod.put(annotation.tag() , method);
            }
        }
            
            // 调用 showUserList 方法
            // 如果有参数,可以其实还可以使用 反射 把参数做类型转化。
            keyMethod.get("/users").invoke(controller);
            
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
 

上面是建立一个 <tag , Method> 方式,tag 是 String 类型,如果要是需要做复杂得逻辑判断,可以将 tag 转化为 Integer 来实现,每个 bit 位上表示 true or false ,
这样我们判断条件和 Method 的关系建立起来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值