阅读量:2
本文介绍项目中常用的策略模式+工厂模式的案例,该案例是针对策略类比较少的情况;下一篇会讲解策略类比较多的案例,下面直接开始:
案例1:项目中对系统中的客户和销售进行事件通知(短信、邮件、钉钉)
首先要有通知的策略接口,接口里面要有一个方法就是通知的方法
public interface PushChannelStrategy{ // 通知方法 SendResult send(MessagePushParam param,BaseMsg baseMsg); }
有了接口那必然有实现类,三个实现类短信、邮件、钉钉
短信:
@Slf4j @Component public class SmsPushChannelStrategy implements PushChannelStrategy{ @Autowired private NoticeClient noticeClient; @Override public SendResult send(MessagePushParam param,BaseMsg baseMsg){ //1、before send check //2、send sms NoticeResult noticeResult=noticeClient.sendSms(xxxx); sendResult.setMessageStatus(MessageStatusEnum.SUCCESS); return sendResult; } }
邮件:
@Slf4j @Component public class EmailPushChannelStrategy implements PushChannelStrategy{ @Autowired private NoticeClient noticeClient; @Override public SendResult send(MessagePushParam param,BaseMsg baseMsg){ //1、before send check //2、send email Email emailMsg=(Email)baseMsg; NoticeResult noticeResult=noticeClient.sendEmail(xxxx); sendResult.setMessageStatus(MessageStatusEnum.SUCCESS); return sendResult; } }
钉钉:
@Slf4j @Component public class DingTalkPushChannelStrategy implements PushChannelStrategy{ @Autowired private DingTalkClient dingTalkClient; @Override public SendResult send(MessagePushParam param,BaseMsg baseMsg){ //1、before send check //2、send ding talk SendResult sendResult=dingTalkClient.send(xxx); // 其他结果参数组装 return sendResult; } }
然后通过策略工厂来获取具体的策略类:(由于只有三个策略类,所以通过注入的方式对channel进行判断)
@Component public class PushChannelStrategyFactory{ @Autowired private DingTalkPushChannelStrategy dingTalkPushChannelStrategy; @Autowired private SmsPushChannelStrategy smsPushChannelStrategy; @Autowired private EmailPushChannelStrategy emailPushChannelStrategy; public PushChannelStrategy getStrategy(PushChannel pushChannel){ switch(pushChannel){ case DING_TALK: return dingTalkPushChannelStrategy; case SMS: return smsPushChannelStrategy; case EMAIL: return emailPushChannelStrategy; default: throw new RuntimeException("不支持的类型"); } } }
当然策略工厂针对策略实现类比较少的情况还可以这样写:
@Component public class PushChannelStrategyFactory2{ @Autowired private DingTalkPushChannelStrategy dingTalkPushChannelStrategy; @Autowired private SmsPushChannelStrategy smsPushChannelStrategy; @Autowired private EmailPushChannelStrategy emailPushChannelStrategy; private static final Map<PushChannel,PushChannelStrategy> pushChannelBuilderMap=new HashMap<>(); @PostConstruct public void init(){ pushChannelBuilderMap.put(PushChannel.SMS,smsPushChannelStrategy); pushChannelBuilderMap.put(PushChannel.Email,emailPushChannelStrategy); pushChannelBuilderMap.put(PushChannel.DING_TALK,dingTalkPushChannelStrategy); } Public PushChannelStrategy getStrategy(PushChannel PushChannel){ if(PushChannel==null){ return null; } return pushChannelBuilderMap.get(PushChannel); } }
用到的枚举类:
@Getter public enum PushChannel{ SMS("sms","短信"), EMAIL("email","邮件"), DING_TALK("dingTalk","钉钉"); private final String value; PushChannel(String value,String desc){ this.value=value; } public static PushChannel getPushChannel(String pushChannel){ if(pushChannel==null){ return null; } for(PushChannel channel:PushChannel.values()){ if(pushChannel.equals(channel.getValue())){ return channel; } } return null; } }
在使用的时候通过策略工厂里面的方法获取具体的策略类:
@Slf4j @Service public class MessagePushService{ @Autowired private PushChannelStrategyFactory pushChannelStrategyFactory; @Autowired private MessageRecordRepository messageRecordRepository; public ResultDTO<Boolean> pushSync(MessagePushCommand command){ MessagePushParam messagePushParam =MessagePushAssembler.convert(command); //1,业务逻辑处理 //2、根据渠道进行触达 PushChannel pushChannel=messagePushParam.getChannel(); if(pushChannel==null){ throw new MessagePushException(xxx); } //3、获取具体的策略类 PushChannelStrategy pushChannelStrategy=pushChannelStrategyFactory.getStrategy(pushChannel); SendResult sendResult=PushChannelStrategy.send(messagePushParam,xxx); //4,记录落库 return ResultDTO.getSuccessResult(true); } }
到此该版本的策略模式+工厂模式就结束了,欢迎点评和指出不足之处。