This is the first day of my participation in the August More Text challenge

1. Scene Description

Often in projects, we see too much if-else code as shown below. If there are too many conditions, the logic is confusing and error-prone. If you add a new service, add an if else, which is difficult to maintain and poor to read.

if(a){
    
}else if(b){
    
}else if(c){
    
}else{}Copy the code

What are strategic patterns?

Policy pattern is a decoupled method, which encapsulates the algorithm and separates the algorithm invocation from the algorithm itself. With the policy pattern, client code does not need to be tweaked and algorithms can be replaced with each other because different algorithms implement the same interface.

Here’s a practical example of how to use the policy pattern to avoid excessive if-else statements.

2. Define the policy interface

public interface BusinessExecutor {
	void handleMessage(String record);
}
Copy the code

3. Implementation strategy

Implement interfaces and rewrite processing logic according to different strategies.

@Slf4j
@Component("simpleBusinessExecutor")
public class SimpleBusinessExecutor implements BusinessExecutor {
	@Override
	public void handleMessage(String record) {
		log.info("simple {}", record); }}Copy the code
@Slf4j
@Component("intentBusinessExecutor")
public class IntentBusinessExecutor implements BusinessExecutor {
	@Override
	public void handleMessage(String record) {
		log.info("intent {}",record); }}Copy the code

4. Policy management

Define the policy context. Since Spring IOC already instantiates the class into the container via reflection, we only need to get the object instance based on the business type. Here we use ApplicationContext to get the policy object instance Bean.

@Slf4j
@Component
public class BusinessExecutorManager {

	@Autowired
	private ApplicationContext applicationContext;

	public BusinessExecutor getExecutor(Byte type) {
		BussinessTypeEnum[] values = BussinessTypeEnum.values();
		if (values.length <= 0) {
			return null;
		}
		for (BussinessTypeEnum value : values) {
			try {
				if (Objects.equals(type, value.getCode())) {
					return(BusinessExecutor) applicationContext.getBean(value.getBeanName()); }}catch (Exception e) {
				log.error("Get business Ecutor exception", e);
				return null; }}return null; }}Copy the code

In this step, we need a way to get instances of objects based on business type Type reflection, using enumerations to maintain the correspondence between the two.

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum BussinessTypeEnum {

	INTENT_BUSINESS(Byte.parseByte("1"), "intentBusinessExecutor"."Simple business"),
	SIMPLE_BUSINESS(Byte.parseByte("2"), "simpleBusinessExecutor"."Intended business");

	private Byte code;
	private String beanName;
	private String desc;

}
Copy the code

However, there is also a lack of elegance, is that the mapping between the business type type and the processing class still needs to be manually maintained, which is not smart enough.

5. Run (using policies)

@Slf4j
@Component
public class ModelMessage {

	@Autowired
	private BusinessExecutorManager businessExecutorManager;

	protected void execute(a) {
                Byte bussinessType = Byte.parseByte("1");
                String message = "test";
		BusinessExecutor businessExecutor = businessExecutorManager.getExecutor(bussinessType);
		if(businessExecutor! =null){ businessExecutor.handleMessage(message); }}}Copy the code

The results are as follows:

simple test

Now, if you add business logic, you just need to add another class to handle policy. Each processing logic is independent of each other. There is no need to add else-if to handle the new business logic.