策略模式+工厂模式结合案例

首先有个推送数据的接口,
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,返回对应的实现类。

 

posted @ 2022-08-01 16:45  Mr.Duanxj  阅读(353)  评论(0编辑  收藏  举报