1、问题场景
监听上游服务MQ消息,根据不同的操作类型(opCode)做相对应的个性化处理。目前接收的就三种,随着业务拓展还会不断的增加,所以此处按照原来的if-else去处理会显得比较呆。
2、一般实现(if-else)
public Action consume(Message message, ConsumeContext context) {
boolean success = true;
long startTime = System.currentTimeMillis();
try {
String content = new String(message.getBody(), StandardCharsets.UTF_8);
log.info("op_message_listener receive_msg: {}", content);
DetailsDO detailsDO = JSONObject.parseObject(content, DetailsDO.class);
String opCode = detailsDO.getOpCode().getCode();
if (OpCodeEnum.OP_CODE_100.getCode().equals(opCode)) {
opCode_100(detailsDO);
} else if (OpCodeEnum.OP_CODE_110.getCode().equals(opCode)) {
opCode_110(detailsDO);
} else if (OpCodeEnum.OP_CODE_120.getCode().equals(opCode)) {
opCode_120(detailsDO);
}
} catch (Exception e) {
success = false;
log.error("op_message_listener handle_error", e);
}
MonitorLogUtil.addSunFireLog("op_message_listener_事件操作消息监听" + "#" + "message.getMsgID()", startTime, success);
return (success || !errorRetry) ? Action.CommitMessage : Action.ReconsumeLater;
}
以上代码实现有如下的缺点:
针对以上代码的缺点我们可以利用策略模式来消除臃肿复杂的if-else。
3、策略+简单工厂
策略模式(Strategy Pattern)定义了一组策略,分别在不同类中封装起来,每种策略都可以根据当前场景相互替换,从而使策略的变化可以独立于操作者。比如我们要去某个地方,会根据距离的不同(或者是根据手头经济状况)来选择不同的出行方式(共享单车、坐公交、滴滴打车等等),这些出行方式即不同的策略。
简单工厂提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
3.1、定义抽象的数据策略接口public interface IEventService {
void opHandler(DetailsDO detailsDO);
String getOpCode();
}
其中的opHandler方法是执行具体匹配数据逻辑的接口
3.2、具体策略实现类@Slf4j
@Service("xxxEventService")
public class XxxEventServiceImpl implements IEventService {
@Override
public void opHandler(DetailsDO detailsDO) {
// 业务逻辑实现
System.out.println("------xxx opHandler------");
}
@Override
public String getOpCode() {
return OpCodeEnum.OP_CODE_100.getCode();
}
}
3.3、定义策略工厂
@Component
public class EventServiceFactory implements InitializingBean, ApplicationContextAware {
private ApplicationContext appContext;
private static final Map EVENT_SERVICE_MAP = new HashMap<>(8);
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
appContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
// 将 Spring 容器中所有的 IEventService 注册到 EVENT_SERVICE_MAP
appContext.getBeansOfType(IEventService.class)
.values()
.forEach(handler -> EVENT_SERVICE_MAP.put(handler.getOpCode(), handler));
}
public static IEventService getHandler(String opCode) {
return EVENT_SERVICE_MAP.get(opCode);
}
}
3.4、调用实现
public Action consume(Message message, ConsumeContext context) {
boolean success = true;
long startTime = System.currentTimeMillis();
try {
String content = new String(message.getBody(), StandardCharsets.UTF_8);
log.info("op_message_listener receive_msg: {}", content);
DetailsDO detailsDO = JSONObject.parseObject(content, DetailsDO.class);
String opCode = detailsDO.getOpCode().getCode();
// 替换if-else --begin
IEventService eventService = EventServiceFactory.getHandler(opCode);
eventService.opHandler(detailsDO);
// 替换if-else --end
} catch (Exception e) {
success = false;
log.error("op_message_listener handle_error", e);
}
MonitorLogUtil.addSunFireLog("op_message_listener_事件操作消息监听" + "#" + "message.getMsgID()", startTime, success);
return (success || !errorRetry) ? Action.CommitMessage : Action.ReconsumeLater;
}



