Optimization of if else statement

preface

In daily development, we often encounter judging which code and method the program should go according to the incoming value. Usually, we use if else statement to judge. If there are many cases of the passed in values, we will write a lot of if else to judge, so the code will appear very bloated and difficult to maintain. The newly added conditions in the later stage are not easy to expand. During the test, the whole if else statement should be tested again, which is very time-consuming and inconvenient. Next, let's introduce several methods. You can make conditional judgment without using if else statements.

Use enumeration

First, define a common interface RoleOperation to represent the operations that different roles can do

package com.gavin.enums;

public interface RoleOperation {

    //Define a method to represent the op (operation) permissions of a role
    String op();
}

Next, we will leave the situation of different roles to the enumeration class to define an enumeration class with different permissions for different roles

package com.gavin.enums;

public enum RoleEnum implements RoleOperation{

    //Define the operation authority of a super administrator (with AAA operation authority)
    ROLE_ROOT_ADMIN {
        @Override
        public String op() {
            return "ROLE_ROOT_ADMIN:has AAA permission";
        }
    },

    //Define the operation authority of an order administrator (with BBB operation authority)
    ROLE_ORDER_ADMIN {
        @Override
        public String op() {
            return "ROLE_ORDER_ADMIN:has BBB permission";
        }
    },

    //Define the operation authority of an ordinary user (with CCC operation authority)
    ROLE_NORMAL {
        @Override
        public String op() {
            return "ROLE_NORMAL:has CCC permission";
        }
    };
}

Next, the call becomes extremely simple, one line of code is enough, and if/else goes up in smoke:

package com.gavin.enums;

public class JudgeRole {

    public static void main(String[] args) {
        String roleName = "ROLE_ROOT_ADMIN";
        String operation = RoleEnum.valueOf(roleName).op();
        System.out.println("Operation authority:" + operation);
    }
}


In this way, if I want to extend the condition in the future, I just need to add code to the enumeration class

Use factory mode

Different branches do different things, which obviously provides an opportunity to use the factory mode. We just need to define different situations separately and aggregate them in the factory class.

First, define business classes for different roles:

package com.gavin.factory;

import com.gavin.enums.RoleOperation;

public class RootAdminRole implements RoleOperation {

    //Define attribute values
    private String roleName;

    //Parametric construction method
    public RootAdminRole (String roleName) {
        this.roleName = roleName;
    }

    //Implement the RoleOperation interface, and then override the interface method
    @Override
    public String op() {
        return roleName + " has AAA permission";
    }
}

package com.gavin.factory;

import com.gavin.enums.RoleOperation;

public class OrderAdminRole implements RoleOperation {

    //Define attribute values
    private String roleName;

    //Parametric construction method
    public OrderAdminRole(String roleName) {
        this.roleName = roleName;
    }

    //Implement the RoleOperation interface, and then override the interface method
    @Override
    public String op() {
        return roleName + " has BBB permission";
    }
}

package com.gavin.factory;

import com.gavin.enums.RoleOperation;

public class NormalRole implements RoleOperation {

    //Define attribute values
    private String roleName;

    //Parametric construction method
    public NormalRole(String roleName) {
        this.roleName = roleName;
    }

    //Implement the RoleOperation interface, and then override the interface method
    @Override
    public String op() {
        return roleName + " has CCC permission";
    }
}

Next, write a factory class RoleFactory to aggregate the above different roles:

package com.gavin.factory;

import com.gavin.enums.RoleOperation;

import java.util.HashMap;
import java.util.Map;

public class RoleFactory {

    //Define a Map collection. After static modification, it will be loaded into the heap together with the class
    //The loading order precedes constants, variables, and methods that are not decorated with static
    static Map<String, RoleOperation> map = new HashMap<>();

    //Define a static method for initialization
    static {
        map.put("ROLE_ROOT_ADMIN", new RootAdminRole("ROLE_ROOT_ADMIN"));
        map.put("ROLE_ORDER_ADMIN", new OrderAdminRole("ROLE_ORDER_ADMIN"));
        map.put("ROLE_NORMAL", new NormalRole("ROLE_NORMAL"));
    }

    //Define a static method to obtain operation permission and provide it to other method calls
    public static RoleOperation getOp(String roleName) {
        return map.get(roleName);
    }
}

Next, with the help of the above factory, the business code call only needs one line of code:

package com.gavin.factory;

public class JudgeRole02 {

    public static void main(String[] args) {
        /**
         * Using the factory mode implementation idea, first call the getOp method in the RoleFactory class to find the permissions in the corresponding role object
         * Then call the op() method in the object to obtain the permission information of the role
         */
        String roleName = "ROLE_ROOT_ADMIN";
        String operation = RoleFactory.getOp(roleName).op();
        System.out.println("Operation authority:" + operation);
    }
}

Execution results:

In this way, it is easy to expand conditions in the future. You only need to add new codes without changing the previous business codes, which is very in line with the "opening and closing principle".

Use policy mode

In fact, there is little difference between strategy mode and factory mode!

On the basis of the above factory pattern code and according to the guiding ideology of the policy pattern, we also create a so-called policy context class, which is named RoleContext here:

package com.gavin.strategy;

import com.gavin.enums.RoleOperation;

public class RoleContext {

    //Define replaceable policies and pass in different policy objects, and the business will change accordingly
    private RoleOperation roleOperation;

    public RoleContext(RoleOperation roleOperation) {
        this.roleOperation = roleOperation;
    }

    //Define the method for obtaining role permissions
    public String execute() {
        return roleOperation.op();
    }
}

Obviously, the parameter operation passed in above means different "policies". We can get different operation results by passing in different roles in the business code:

package com.gavin.strategy;

import com.gavin.enums.RoleOperation;
import com.gavin.factory.NormalRole;
import com.gavin.factory.OrderAdminRole;
import com.gavin.factory.RootAdminRole;

public class JudgeRole03 {

    public static void main(String[] args) {
        JudgeRole03 judgeRole03 = new JudgeRole03();
        String operation = judgeRole03.judge(new RootAdminRole("ROLE_ROOT_ADMIN"));
        System.out.println("operation=" + operation);
        String operation2 = judgeRole03.judge(new OrderAdminRole("ROLE_ORDER_ADMIN"));
        System.out.println("operation2=" + operation2);
        String operation3 = judgeRole03.judge(new NormalRole("ROLE_NORMAL"));
        System.out.println("operation3=" + operation3);
    }

    //Define a method to call the execute() method to obtain role permissions in the RoleContext object
    public String judge(RoleOperation roleOperation) {
        RoleContext roleContext = new RoleContext(roleOperation);
        return roleContext.execute();
    }
}

The above are several commonly used optimization methods for if else statements. Before writing code, you still have to think more about whether there is a more scalable writing method!

Keywords: Java

Added by bucko on Mon, 03 Jan 2022 22:16:57 +0200