java设计模式之:策略模式+工厂模式整合案例实战(一)

本文介绍项目中常用的策略模式+工厂模式的案例,该案例是针对策略类比较少的情况;下一篇会讲解策略类比较多的案例,下面直接开始:

案例1:项目中对系统中的客户和销售进行事件通知(短信、邮件、钉钉)

首先要有通知的策略接口,接口里面要有一个方法就是通知的方法

java 复制代码
public interface PushChannelStrategy{
   // 通知方法
   SendResult send(MessagePushParam param,BaseMsg baseMsg);

}

有了接口那必然有实现类,三个实现类短信、邮件、钉钉

短信:

java 复制代码
@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;
   }
}

邮件:

java 复制代码
@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;
   }
}

钉钉:

java 复制代码
@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进行判断)

java 复制代码
@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("不支持的类型");
           }
     }
}

当然策略工厂针对策略实现类比较少的情况还可以这样写:

java 复制代码
@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);
    }
}
       

用到的枚举类:

java 复制代码
@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;
  }
}
   

在使用的时候通过策略工厂里面的方法获取具体的策略类:

java 复制代码
@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);
    }
 }

到此该版本的策略模式+工厂模式就结束了,欢迎点评和指出不足之处。

相关推荐
略略略咯咯7 小时前
(总结)设计模式
设计模式
嘻哈∠※9 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_7989 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander25810 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅10 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
极创信息12 小时前
系统安全隐患全方位排查方案:标准化渗透测试全流程
java·opencv·struts·数据挖掘·eclipse·语音识别·hibernate
汉字萌萌哒12 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
喜欢的名字被抢了13 小时前
程序出问题怎么查,以及如何让它不掉线
java·运维·数据库
数据知道13 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
2601_9499506314 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐