策略模式+工厂模式结合案例
首先有个推送数据的接口,
public interface MsgTypeStrategy { /** * 不同消息类型不同的推送策略 * @param dto 推送请求数据 * @return 是否推送成功 */ boolean push(MsgRequestDTO dto);
/** * 消息类型 */ SYSTEM_APP(0, "APP系统消息"), NORMAL_SMS(1, "普通短信"), CODE_SMS(2, "验证码短信"), VOICE_SMS(3, "语音短信"), MP_WX(4, "微信公众号模板消息"), MA_WX(5, "微信小程序订阅消息"), OPENLIFE_ALIPAY(6, "支付宝生活号消息"), MINI_ALIPAY(7, "支付宝小程序消息"), PRIVATE_APP(8, "APP单聊消息"), HOME_ALIPAY(9, "支付宝首页消息") ;
不同的消息类型有不同的推送方式。,都实现推送接口。
@Component(value = "HOME_ALIPAY") @Slf4j public class HomeAlipayMsgTypeStrategy implements MsgTypeStrategy { @Autowired private MsgClientConfigRepository msgClientConfigRepository; @Autowired private RabbitTemplate rabbitTemplate; @Autowired private MsgThirdTokenRepository msgThirdTokenRepository; @Autowired private ApplicationEventPublisher applicationEventPublisher; @Override public boolean push(MsgRequestDTO dto) { String templateContent = dto.getTemplateContent(); JSONObject templateContentJson = JSONUtil.parseObj(templateContent); String scope = templateContentJson.getStr("scope"); Optional<MsgThirdToken> msgThirdTokenOptional = msgThirdTokenRepository.findByFromTypeAndUserIdAndScope(dto.getReceiver(), dto.getUserId(), scope); if (!msgThirdTokenOptional.isPresent()) { log.error("消息推送-支付宝首页消息-第三方token不存在, fromType:{}, userId:{}, scope:{}", dto.getReceiver(), dto.getUserId(), scope); return false; } MsgThirdToken msgThirdToken = msgThirdTokenOptional.get(); String bodyStr = templateContentJson.getStr("content"); JSONObject requestContentJson = JSONUtil.parseObj(dto.getRequestContent()); requestContentJson.set("openId", msgThirdToken.getOpenId()); requestContentJson.set("isvPid", templateContentJson.getStr("isvPid")); requestContentJson.set("hospAppId", templateContentJson.getStr("hospAppId")); requestContentJson.set("hospitalRegisterId", templateContentJson.getStr("hospitalRegisterId")); String url = "alipays://platformapi/startapp?appId=" + templateContentJson.getStr("hospAppId") + "&page="; String encodeUrl = URLUtil.encodeAll(dto.getUrl()); requestContentJson.set("merchantOrderLinkPage", url + encodeUrl); String body = TemplateUtil.convertContent(JSONUtil.toJsonStr(requestContentJson), bodyStr); body = TemplateUtil.convertUrl(body,url); body = TemplateUtil.convertCalculator(body, 2); body = TemplateUtil.convertTime(body); MsgResponseDTO responseDTO = sendHomeAlipay(templateContentJson, body, msgThirdToken.getAccessToken()); applicationEventPublisher.publishEvent(new MsgLogEvent<>(new MsgLogDTO(dto, responseDTO))); if (!responseDTO.getSuccess()) { log.error("消息推送-支付宝首页消息-失败, userId:{}", dto.getUserId()); return false; } return true; }
下面是运用:先建立一个工厂类,初始化加载的时候,会把所有的实现类都加载到这个Map中,k-实现类名称,v-返回该类
@Service public class MsgTypeFactory { @Autowired private Map<String, MsgTypeStrategy> strategyMap;
public MsgTypeStrategy getMsgTypeStrategy(String msgTypeEnum) { if (Objects.isNull(msgTypeEnum)) { throw new IllegalArgumentException("请输入对应的消息类型"); } return strategyMap.get(msgTypeEnum); } }
消息调用的时候,根据消息类型,调用工厂类,返回对应的实现类。触发推送
@Slf4j @Component public class MqConsumer { @Autowired private MsgTypeFactory msgTypeFactory; @RabbitListener(queues = MqQueueConstant.APP_QUEUE) public void appQueue(String msg) { sendMsg(msg); } @RabbitListener(queues = MqQueueConstant.SMS_QUEUE) public void smsQueue(String msg) { sendMsg(msg); } @RabbitListener(queues = MqQueueConstant.WX_QUEUE) public void wxQueue(String msg) { sendMsg(msg); } @RabbitListener(queues = MqQueueConstant.ALIPAY_QUEUE) public void alipayQueue(String msg) { sendMsg(msg); } private void sendMsg(String msg) { MsgRequestDTO dto = JSONUtil.toBean(msg, MsgRequestDTO.class); MsgTypeEnum msgType = dto.getMsgType(); MsgTypeStrategy msgTypeStrategy = msgTypeFactory.getMsgTypeStrategy(msgType.name());//关键是这步 msgTypeStrategy.push(dto); } }
总结:一个接口,有多种实现时,在项目起来,先加载一个工厂类(里面有这个接口的全部实现类名称k 接口实现类k),k-v格式,报漏接口,根据k,返回对应的实现类。