当前位置:网站首页>Don't you know the usage scenario of the responsibility chain model?

Don't you know the usage scenario of the responsibility chain model?

2022-04-23 14:39:00 Fried stewed sugar chestnut

summary

In code, we often have if…else… Judge , If one condition is not satisfied, make the next judgment , This is similar to the responsibility chain model , It's just that the responsibility chain model is filtered by objects .

scene

In the Internet of things industry , A device will push data to the server at a certain frequency , It is convenient for the server to collect and monitor the data of the machine , There are many types of this data . For example, for a doll machine : There will be data of equipment status 、 Data of equipment positioning 、 Equipment alarm data and other data . Each type of data consists of many fields , For example, the device status data contains : current time 、 Machine number 、 The state of the machine ( go online 、 Offline 、 offline ), It is generally transmitted in binary form , For convenience, it is assumed that the equipment is JSON Submit it in the format of , I receive the data and process it accordingly .

image-20220421214953234

Ordinary code implementation

The first thing you can think of is to use if…else…, If it is the data of equipment alarm, I will use the equipment alarm processor to process , Super simple , Start coding ~

1、 Entity class

DeviceAlarm class

package com.ylc.model;

import lombok.Data;

/**
 *  Device status entity class 
 * @author yanglingcong
 * @date 2022/4/20 21:08
 */
@Data
public class DeviceStatus {


    /**
     *  Update time 
     */
    private  long updateTime;

    /**
     *  state 
     * 0  Not prepared 
     * 1  Get ready 
     * 2  The normal operation 
     * 3  abnormal 
     */
    private Integer state;

    /**
     *  data type 
     */
    private String type;

}

DeviceGps class

/**
 *  equipment GPS Entity class 
 *
 * @author yanglingcong
 * @date 2022/4/20 21:08
 */
@Data
public class DeviceGps {

    /**
     *  longitude 
     */
    private Float longitude;

    /**
     *  latitude 
     */
    private Float latitude;


    /**
     *  Horizontal component accuracy factor :
     */
    private Float hdop;

}

DeviceAlarm class

package com.ylc.model;

import lombok.Data;

/**
 *  Equipment alarm entity class 
 *
 * @author yanglingcong
 * @date 2022/4/20 21:08
 */
@Data
public class DeviceAlarm {

    /**
     *  Alarm message 
     */
    private String alarmMsg;

    /**
     *  Alarm status 
     */
    private Integer alarmStatus;
}

2、 Enumeration type of the message

package com.ylc.model;

import lombok.Getter;

/**
 *  Device message enumeration type 
 * @author yanglingcong
 * @date 2022/4/20 21:08
 */
@Getter
public enum eventEnum {

    STATUS("10001"),

    ALARM("10002"),

    GPS("10003");

    private String code;

    eventEnum(String code){
        this.code=code;
    }
}

3、 Event interface

/**
 *  Processor interface 
 * @author yanglingcong
 * @date 2022/4/19 22:59
 */
public interface AbstractHandler {

    String getEventType();

    void handle(JSONObject jsonObject);

}

3、 Event handling

DeviceAlarmEvent

/**
 *  Equipment alarm events 
 * @author yanglingcong
 * @date 2022/4/19 22:59
 */
@Slf4j
@Component
public class DeviceAlarmEvent   implements  AbstractHandler{

    @Override
    public String getEventType() {
        return eventEnum.ALARM.getCode();
    }

    @Override
    public void handle(JSONObject jsonObject) {
        DeviceAlarm deviceAlarm = jsonObject.toJavaObject(DeviceAlarm.class);
        log.info(" Equipment alarm events are handled ");
        // Business processing .....
    }
}

DeviceGpsEvent

/**
 *  Device location event 
 * @author yanglingcong
 * @date 2022/4/19 22:59
 */
@Component
@Slf4j
public class DeviceGpsEvent implements AbstractHandler{

    @Override
    public String getEventType() {
        return eventEnum.GPS.getCode();
    }

    @Override
    public void handle(JSONObject jsonObject) {
        DeviceGps deviceGps = jsonObject.toJavaObject(DeviceGps.class);
        // Business processing .....
        log.info(" The device location event is processed ");
    }
}

DeviceStatusEvent

/**
 *  Device status events 
 * @author yanglingcong
 * @date 2022/4/19 22:59
 */
@Slf4j
@Component
public class DeviceStatusEvent implements  AbstractHandler{

    @Override
    public String getEventType() {
        return eventEnum.STATUS.getCode();
    }

    @Override
    public   void  handle(JSONObject jsonObject){
        DeviceStatus deviceStatus = jsonObject.toJavaObject(DeviceStatus.class);
        // Business processing .....
        log.info(" Device status events are handled ");
    }
}

4、 Message distribution center

package com.ylc.handle;

import com.alibaba.fastjson.JSONObject;
import com.ylc.model.eventEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 *  Data event processing class 
 * @author yanglingcong
 */
@Slf4j
@Component
public class PushEvent {

    /**
     *  Data is distributed to the corresponding event handler 
     */
    public void dispatch(JSONObject jsonObject){
        String code = (String) jsonObject.get("type");
        // If it is equipment status data 
        if(code.equals(eventEnum.STATUS.getCode())){
            log.info(" Start processing device status data ");
            DeviceStatusEvent statusEvent=new DeviceStatusEvent();
            statusEvent.handle(jsonObject);
        }
        // If it is equipment positioning data 
        else if(code.equals(eventEnum.GPS.getCode())){
            log.info(" Start processing equipment positioning data ");
            DeviceGpsEvent deviceGpsEvent=new DeviceGpsEvent();
            deviceGpsEvent.handle(jsonObject);
        }
        // If it is equipment alarm data 
        else if(code.equals(eventEnum.ALARM.getCode())){
            log.info(" Start processing equipment positioning data ");
            DeviceStatusEvent statusEvent=new DeviceStatusEvent();
            statusEvent.handle(jsonObject);
        }
    }

}

6、 test

@Slf4j
public class MessageHandleTest {

    @Test
    public void  testDeviceStatus(){
        DeviceStatus deviceStatus=new DeviceStatus();
        deviceStatus.setType(eventEnum.STATUS.getCode());
        deviceStatus.setUpdateTime(1653532367);
        deviceStatus.setState(1);
        JSONObject jsonObject= JSON.parseObject(JSONObject.toJSONString(deviceStatus));
        PushEvent pushEvent=new PushEvent();
        log.info(" Start distributing messages :{}",deviceStatus.toString());
        pushEvent.dispatch(jsonObject);
    }

}

Running results

image-20220421221949165

But there will be many problems , If there are other types of data, you have to add judgment , The order of judging this condition is also written dead , Very inflexible , Next, use the responsibility chain model to optimize

The chain of responsibility realizes

1、 Entity class A little

2、 Event handling A little

3、 Message distribution center

package com.ylc.handle;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 *  Data event processing class 
 * @author yanglingcong
 */
@Slf4j
@Component
public class PushEvent implements ApplicationContextAware {

     /**
     *  Implementation class collection 
     * */
    private Map<String, List<AbstractHandler>> routerMap;

    @Autowired
    ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.routerMap =applicationContext.getBeansOfType(AbstractHandler.class).values()
                .stream().collect(Collectors.groupingBy(AbstractHandler::getEventType));
    }

    /**
     *  Data is distributed to the corresponding event handler 
     */
    public void dispatch(JSONObject jsonObject){
        String code = (String) jsonObject.get("type");
        List<AbstractHandler> pushEventHandlers= this.routerMap.get(code);
        for (AbstractHandler pushEventHandler : pushEventHandlers) {
            log.info(" Start to deal with {} event ",pushEventHandler.getEventType());
            pushEventHandler.handle(jsonObject);
        }
    }
}

4、 test

package com.ylc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ylc.handle.AbstractHandler;
import com.ylc.handle.PushEvent;
import com.ylc.model.DeviceStatus;
import com.ylc.model.eventEnum;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class MessageHandleTest {

    @Autowired
    PushEvent pushEvent;

    @Test
    public void  testDeviceStatus(){
        DeviceStatus deviceStatus=new DeviceStatus();
        deviceStatus.setType(eventEnum.STATUS.getCode());
        deviceStatus.setUpdateTime(1653532367);
        deviceStatus.setState(1);
        JSONObject jsonObject= JSON.parseObject(JSONObject.toJSONString(deviceStatus));
        log.info(" Start distributing messages :{}",deviceStatus.toString());
        pushEvent.dispatch(jsonObject);
    }

}

image-20220423140135494

  • If there is a new device message type , Just add a new event handling class , Other codes don't need to change , This is in line with the open and closed principle and the single principle , It also increases the flexibility of the program .
  • We don't need to know which type to use , Leave it to the program runtime to handle
  • Use Map The way to assemble , Find the corresponding processor directly from the set according to the characteristics , Similar to the way other blog settings use the next handler to judge , If the chain is long, it is not appropriate to use the next handler method , You need to traverse from the beginning to the end .
  • You can also control the order of requests , Set by adding a sort field

summary

The responsibility chain model is actually flexible if..else.. sentence , Connect multiple processors into a chain . After receiving the request , It will “ inquiry ” Whether each processor can handle it . In this way, all processors have the opportunity to process the request

Use scenarios

  • When multiple processors must be executed in sequence , You can use this mode
  • If the required processor and its order must be changed at run time , You can use the responsibility chain model
  • When a program needs to handle different kinds of requests in different ways , And when the request type and order are unknown in advance , You can use the responsibility chain model

版权声明
本文为[Fried stewed sugar chestnut]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231439160668.html