Why replace if/else

In the development process, it is inevitable to use if/else to make logical judgment. If the logic is very complex, the judgment logic will be changed frequently or the judgment logic will be added later, then if/else will lead to code that is difficult to understand and difficult to maintain. It is recommended that we use strategy mode instead of if/ ELSE

The strategy pattern

The non-fixed functions are extracted, interfaces and implementation classes are defined independently, and aggregated in the Manager class to achieve the effect of assembling classes, and the following effects can be achieved:

  1. Readability, programming normative, easy for other programmers to read and understand
  2. Scalability, maintainability, very convenient when you need to add new features, low cost
  3. Reliability: New or reduced functions have no impact on existing functions
  4. Meet the open closed principle

The sample

If the employee is late for work >=3 times, he/she will be deducted 100 yuan each time. If the employee is late for work >= 5 times, he/she will be added 50 yuan each time. No matter whether the demand is reasonable, it is just an assumption.

Define an object to record the number of lateness and overtime

StaffData staffData = StaffData.builder()
    .chidao(3)
    .jiaban(10)
    .build();
Copy the code

The code for using if/else is as follows:

public static int calc(StaffData staffData) {
    int total = 0;
    if(staffData.getChidao() ! =null && staffData.getChidao() >= 3) {
        total -= staffData.getChidao() * 100;
    }
    if(staffData.getJiaban() ! =null && staffData.getJiaban() > 5) {
        total += staffData.getJiaban() * 50;
    }
    return total;
}

System.out.println("Bonus =" + calc(staffData));
Copy the code

If the requirement is increased later and the rule of asking for leave is added to StaffData, and 100 yuan is deducted for each leave over 3 times, then you need to continue to add if in the CALC method

If a new rule is added, the number of lateness and basic salary should be added to StaffData. If there are more than 5 times of leave and more than 5 times of lateness, half of the basic salary will be deducted directly. Code should still be added to the CALC method. Improper modification will also lead to errors in the original logic

Adopting a strategic model

First define a Policy interface, usually define the canApply method to make logical judgment, define the apply method to execute the corresponding business logic

public interface Policy {
    /** * Whether the current policy matches **@param data
     * @return* /
    boolean canApply(StaffData data);

    /** * Execute policy **@param data
     * @return* /
    int apply(StaffData data);
}
Copy the code

Define a policy management class. This class is responsible for injecting all policies, and then provides an apply method to iterate over all policies and do the corresponding processing to simplify external calls

@Component
public class PolicyManager {
    @Autowired
    private List<Policy> policies;

    public int apply(StaffData data) {
        int total = 0;
        for (Policy policy : policies) {
            if(policy.canApply(data)) { total += policy.apply(data); }}returntotal; }}Copy the code

Now you can define the policies you need

/** * rule matches */ if late >=3 times

@Component
public class Test1Policy implements Policy {
    @Override
    public boolean canApply(StaffData data) {
        returndata.getChidao() ! =null && data.getChidao() >= 3;
    }

    @Override
    public int apply(StaffData data) {
        // A charge of 100 will be deducted for each lateness
        return -data.getChidao() * 100; }}Copy the code

Define one more policy

/** * If you work more than 5 hours, you will be matched */

@Component
public class Test2Policy implements Policy {
    @Override
    public boolean canApply(StaffData data) {
        returndata.getJiaban() ! =null && data.getJiaban() > 5;
    }

    @Override
    public int apply(StaffData data) {
        // Extra 50 per overtime
        return data.getJiaban() * 50; }}Copy the code

Finally, test if the logic is correct

@SpringBootApplication
public class PolicyTest {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(PolicyTest.class, args);
        PolicyManager manager = context.getBean(PolicyManager.class);

        StaffData staffData = StaffData.builder()
                .chidao(3)
                .jiaban(10)
                .build();
        System.out.println("Bonus ="+ manager.apply(staffData)); }}Copy the code

When adding computing rules in the later period, a new policy class can be implemented, without modifying the original written policy class, and the code is very clear. Each policy class is only responsible for its own business to deal with