SpringBoot uses the policy pattern

Posted by brainstem on Wed, 02 Feb 2022 06:27:43 +0100

preface

In the actual business code, we often encounter such code:

String type = actualService.getRealtype(uid);
if(type.equals("typeA")){
    // do func A
}else if(type.equals("typeB")){
    // do func B
}else if(type.equals("typeC")){
    // do func C
}else[
   //...
}

Java

Copy

This if else or switch case code will judge the branch type in each branch, and then execute different methods to obtain the results. When the code branches are relatively few and it is determined that they will not increase, this method is also completely ok. However, when there are many branches and branch judgment conditions may be added later, this method violates the single responsibility and opening and closing principle, Therefore, when we encounter this situation in our development work, the first thought is to optimize the "bad taste" in the code. One of the methods is to consider whether we can rewrite the code with the policy mode and decouple the code from the business logic, which is conducive to the subsequent maintenance work.

The policy pattern is simply to rewrite different methods through the implementation interface, so as to automatically obtain and execute the selected policy methods through the context.

Practical use

The following is the implementation strategy pattern of dependency injection based on SpringBoot. The assumption scenario is as follows: a customer needs to order multiple resources. Each resource is in different resource pools, and the resources under different resource pools are also different. Here, the original if else code logic is optimized into a policy mode.

First, we implement a ResourceStrategy interface and define the abstract method of selecting resources:

public interface ResourceStrategy {
    String orderInformation(String id);
}

Java

Copy

Then, according to the judgment conditions in if else, three resource classes are constructed to implement the ResourceStrategy interface:

@Component("A")
public class ResourceA implements ResourceStrategy {
   @override
   public String orderInformation(String id){
      System.out.println("Policy selection: Strategy A");
      return "A";
   }
}

Java

Copy

@Component("B")
public class ResourceB implements ResourceStrategy {
   @override
   public String orderInformation(String id){
      System.out.println("Policy selection: Strategy B");
      return "B";
   }
}

Java

Copy

@Component("C")
public class ResourceC implements ResourceStrategy {
   @override
   public String orderInformation(String id){
      System.out.println("Policy selection: Strategy C");
      return "C";
   }
}

Java

Copy

Note that each class needs to be labeled with the policy category name.

Then we need to write a SimpleContext class to store our policy categories. At this time, Spring's dependency injection and automatic discovery are used.

@Service
public class SimpleContextService {
    @Autowired
    private final Map<String, Strategy> strategyMap = new ConcurrentHashMap<>();
 
    public SimpleContext(Map<String, ResourceStrategy > strategyMap) {
        this.strategyMap.clear();
        strategyMap.forEach(strategyMap::put);
    }
 
    public String getResource(String poolId){
        return strategyMap.get(poolId).orderInformation(poolId);
    }
}

Java

Copy

Next is our actual call scenario ~, as follows:

@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    private SimpleContextService contextService;
 
    @GetMapping("/choose")
    public String choose(@RequestParam String poolId){
        return simpleContext.getResource(poolId);
    }
 
}

Java

Copy

Then, when our input parameter poolId is passed into "A", the returned results are as follows:

Policy selection: Strategy A
A

Java

Copy

Similarly, different simultaneous interpreting strategies will enter different strategies. After this simple demo, you can see that you can automatically get different resources by obtaining and entering different resource pool IDs. Through practice, the advantage of using policy mode is that different algorithms can be switched freely through an encapsulated context, eliminating multiple judgments, and has good scalability.

summary

As can be seen from the above, the advantages and disadvantages of the strategy model are very obvious. In our actual business, it also needs to be used according to the situation.

advantage:

  1. The strategy mode conforms to the opening and closing principle
  2. The code is concise, and the conditional transfer statement is automatically obtained from the context
  3. Using policy mode can improve the confidentiality and security of the algorithm

Disadvantages:

  1. Each policy needs to implement a class separately. When there are many policies, a large number of policy classes will be generated, which will "inflate" the code
  2. The client must know all the policies
  3. A series of algorithms in the policy mode have equal status and can be replaced with each other. In fact, they constitute a flat algorithm structure, that is, under a policy interface, there are multiple equal policy algorithms, which is equivalent to brother algorithms. Moreover, only one algorithm is used at runtime, which limits the level of algorithm use and cannot be nested