Map + functional interface instead of strategy mode

This article introduces the specific application of the strategy pattern and how the Map+ functional interface "more perfectly" solves the if-else problem.

demand

I recently wrote a service: query the grantType according to the coupon type resourceType and code resourceId

Method to realize:

  1. Determine which data table to query according to the coupon type resourceType ->
  2. According to the encoding resourceId -> query grantType

There are many types of coupons, corresponding to different database tables:

  • Red envelope
  • Shopping voucher
  • QQ member
  • Takeaway members

The actual coupons are much more than these, this demand is for us to write oneBusiness assignmentLogic of

The first idea that can be thought of is if-else or switch case:

switch(resourceType){
    
    
	case "红包": 
		查询红包的派发方式 
		break;
	case "购物券": 
		查询购物券的派发方式
		break;
	case "QQ会员" :
		break;
	case "外卖会员" :
		break;
	......
	default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式");
		break;
}

If you want to write this, the code of a method is too long, which affects readability. (Don’t look at the case above that there is only one sentence, but there are many lines in the actual situation)

And because the entire if-else code has many lines, it is inconvenient to modify and maintainability is low.

Strategy mode

The strategy mode is to extract the logic in the if statement and write it into a class. If you want to modify a certain logic, you only need to modify the logic of a specific implementation class, and the maintainability will be much better.

The following is the specific structure of the strategy mode (see this blog for details: strategy mode .):

Insert picture description here
The strategy mode is still if-else when the business logic is assigned , but it is better to maintain than the if-else of the first idea. . .

switch(resourceType){
    
    
	case "红包": 
		String grantType=new Context(new RedPaper()).ContextInterface();
		break;
	case "购物券": 
		String grantType=new Context(new Shopping()).ContextInterface();
		break;
	
	......
	default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式");
		break;

But the disadvantages are also obvious:

  • If there are many if-else judgments, there will be many corresponding specific strategy implementation classes.
  • Can't overlook the business logic of the entire dispatch

Map+ functional interface

Use the new features of Java 8 lambda expressions

  • The judgment condition is placed in the key
  • The corresponding business logic is placed in value

The advantage of writing this way isVery intuitive, Can directly see the business logic corresponding to the judgment condition

Requirements: Query the distribution method grantType according to the coupon (resource) type resourceType and the coded resourceId

Above code:

@Service
public class QueryGrantTypeService {
    
    
	
    @Autowired
    private GrantTypeSerive grantTypeSerive;
    private Map<String, Function<String,String>> grantTypeMap=new HashMap<>();

    /**
     *  初始化业务分派逻辑,代替了if-else部分
     *  key: 优惠券类型
     *  value: lambda表达式,最终会获得该优惠券的发放方式
     */
    @PostConstruct
    public void dispatcherInit(){
    
    
        grantTypeMap.put("红包",resourceId->grantTypeSerive.redPaper(resourceId));
        grantTypeMap.put("购物券",resourceId->grantTypeSerive.shopping(resourceId));
        grantTypeMap.put("qq会员",resourceId->grantTypeSerive.QQVip(resourceId));
    }
	
    public String getResult(String resourceType){
    
    
        //Controller根据 优惠券类型resourceType、编码resourceId 去查询 发放方式grantType
        Function<String,String> result=getGrantTypeMap.get(resourceType);
        if(result!=null){
    
    
        	//传入resourceId 执行这段表达式获得String型的grantType
            return result.apply(resourceId);
        }
        return "查询不到该优惠券的发放方式";
    }
}

If the business logic of a single if statement block has many lines, we can extract these business operations and write them as a single Service, namely:

//具体的逻辑操作

@Service
public class GrantTypeSerive {
    
    

    public String redPaper(String resourceId){
    
    
        //红包的发放方式
        return "每周末9点发放";
    }
    public String shopping(String resourceId){
    
    
        //购物券的发放方式
        return "每周三9点发放";
    }
    public String QQVip(String resourceId){
    
    
        //qq会员的发放方式
        return "每周一0点开始秒杀";
    }
}

The input parameter String resourceIdis used to check the database, which is simplified here, and it will not be processed after passing the parameter.

The result of calling with http:

@RestController
public class GrantTypeController {
    
    

    @Autowired
    private QueryGrantTypeService queryGrantTypeService;

    @PostMapping("/grantType")
    public String test(String resourceName){
    
    
        return queryGrantTypeService.getResult(resourceName);
    }
}

Insert picture description here
There are also drawbacks to using Map+ functional interface:
your teammate must know lambda expressions, he won’t let him go to Baidu.

Finally, stroke what this article said:

  1. The strategy mode is completed through interfaces, implementation classes, and logical dispatch. The logic of the if statement block is extracted and written into a class for better maintenance.
  2. The Map+ functional interface Map.get(key)replaces the if-else business dispatch, which can avoid the problem of the increase in classes caused by the strategy model and the difficulty of overlooking the entire business logic.

Guess you like

Origin blog.csdn.net/qq_44384533/article/details/109197926