使用模板方法处理枚举事件的心得

使用模板方法处理枚举事件的心得

1、定义枚举类型

一般情况我们有多重事件类型的情况肯定先自定义一个事件类型的枚举,代码示例如下:

@Getter
public enum EventTypeEnum {
    TYPE1(1,"类型1"),
    TYPE2(2, "类型2"),
    TYPE3(3, "类型3"),
    ;

    private int value;//vn
    private String name;//kn

    public static EventTypeEnum valueOf(int value) {
        for(EventTypeEnum item : EventTypeEnum.values()){
            if(item.value == value){
                return item;
            }
        }
        return null;
    }
    private EventTypeEnum(Integer type, String typeName){
        this.value = type;
        this.name = typeName;
    }
}

2、通常的handler 处理

很自然的我们想到了使用switch来操作,一般switch和枚举是绝配,如下代码展示:

public class EventHandler {

    private void handler(List eventList) {
        if (CollectionUtils.isEmpty(eventList)) {
            return;
        }
        eventList.stream().forEach(e -> {
            EventTypeEnum eventTypeEnum = EventTypeEnum.valueOf(e.getTypeId());
            switch (eventTypeEnum) {
                case TYPE1:
                    //TODO 业务处理
                    break;
                case TYPE2:
                    //TODO 业务处理
                    break;
                case TYPE3:
                    //TODO 业务处理
                    break;
            }
        });
    }
}

但是最近看了一些其他的源码,有一种更好的方式来实现——模板模式;
再上图的例子中我每次增加一种事件,毫无疑问都要来扩展下这个handler类。

3、优雅的handler处理类

@Slf4j
@Component
public class BetterHandlerEvent {

    @Autowired
    private List handlers;

    public void handler(List eventList) {
        if (CollectionUtils.isEmpty(eventList)) {
            return;
        }
        for(DefineEvent event : eventList) {
            handlers.stream().forEach(h -> {
                if(h.accept(event)) {
                    try {
                        h.doHandler(event);
                    }catch (Exception ex) {
                        log.error("handler event exception ,error is {}", ex);
                    }

                }
            });
        }
    }
}

这种以一种模板的方式优雅的实现了时间处理。当我们增加一种时间类型,或者对多重事件类型处理方式进行扩展的时候,这种就很容易实现了扩展。

首先写一个抽象的父类:

public abstract class AbstractHandlerEvent {

    public abstract void doHandler(DefineEvent event);

    public abstract boolean accept(DefineEvent event);
}

就两个方法,一个是否接受该事件的处理,一个是处理逻辑。

而每个事件的处理逻辑都需要继承该方法,如下:

@Service
public class Type1HandlerEvent extends AbstractHandlerEvent {

    @Override
    public boolean accept(DefineEvent event) {
        if(event == null) {
            return false;
        }
        return event.getTypeId() == EventTypeEnum.TYPE1.getValue();
    }

    @Override
    public void doHandler(DefineEvent event) {
        //TODO 业务逻辑
    }
}

两种方式各有优劣。第二种优雅的利用了设计模式的思想。对修改关闭,对扩展开放。

4、应用场景

消息队列消费端的消息处理。

统一触发事件的处理。


可能我不足,但我一直在成长

你可能感兴趣的:(Java)