策略模式2-消息中心的发送策略
需求消息中心改造
这边做的购物中心业务,目前有七千多万用户,一天消息大概两三百万的样子,老业务系统由于种种原因可能实现的不够好,最近领导要改造消息中心.
粮草未动兵马先行,开发前先想想咋开发,这里就考虑到一个比较小的问题,渠道问题,目前消息主要往几个渠道推送,比如APP,公众号,H5,短信等等,这里就要考虑每种情况怎么发送了,由于后面还会有各种渠道,所以考虑扩展性,这里用策略模式进行判断省区大量的if else swith等
demo:
消息实体
/**
* @description: 消息
* @author: zyh
* @create: 2021-06-09 18:56
**/
@Data
public class MsgEntity {
private final String msgType;
private final String openId;
private final String name;
}
抽象策略类
public interface CustomerStrategyAbstract {
void pushStrategy(MsgEntity msg);
}
两种策略
短信
public class SmsPushStrategy implements CustomerStrategyAbstract{
@Override
public void pushStrategy(MsgEntity msg) {
System.out.println(String.format("通过openid:%s ,发送短信给: %s",msg.getOpenId(),msg.getName()));
}
}
微信:
public class WeiXinPushStrategy implements CustomerStrategyAbstract {
@Override
public void pushStrategy(MsgEntity msg) {
System.out.println(String.format("通过openid:%s ,推送微信消息给: %s",msg.getOpenId(),msg.getName()));
}
}
处理类
public class MsgDeal {
//这里渠道可以维护一个枚举类型;
/**
* 短信渠道
*/
private static String sms="sms";
/**
* 微信推送渠道
*/
private static String weixin="weixin";
// 第一种写法
/**
* 缓存所有的策略,当前是无状态的,可以共享策略类对象
*/
private static final Map<String, CustomerStrategyAbstract> strategies = new HashMap<>(4);
static {
strategies.put(sms, new SmsPushStrategy());
strategies.put(weixin, new WeiXinPushStrategy());
}
public static CustomerStrategyAbstract getPushStrategy_1(MsgEntity msg) {
final String type = msg.getMsgType();
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("type should not be empty.");
}
return strategies.get(type);
}
//第二种写法
public static CustomerStrategyAbstract getPushStrategy(MsgEntity msg){
if (sms.equals(msg.getMsgType())){
return new SmsPushStrategy();
}else if (weixin.equals(msg.getMsgType())){
return new WeiXinPushStrategy();
}
return null;
}
//第三种写法,三个渠道写一样的前缀,后缀就写渠道名,然后三个渠道的都放bean容器里,如ModelProvider_1,ModelProvider_2,ModelProvider_3
public static CustomerStrategyAbstract getPushStrategy(MsgEntity msg){
return applicationContext.getBean("ModelProvider_" + msg.getMsgType(), CustomerStrategyAbstract.class);
}
}
测试:
public class MsgPushStrategyTest {
public static void main(String[] args) {
final MsgEntity msgEntity = new MsgEntity("weixin", "123897123", "zyh");
CustomerStrategyAbstract pushStrategy = MsgDeal.getPushStrategy(msgEntity);
Optional.ofNullable(pushStrategy).ifPresent(item->{
pushStrategy.pushStrategy(msgEntity);
});
}
}
总结
- 在请求端,看不到那么多的if else判断,只需要传入对应的策略方式即可,达到了行为解偶的思想,如果我们要进行加渠道加一个类在里面写逻辑,另外在deal类里加个处理渠道即可.
- 我们常见的源码里比如线程池的拒绝策略就是一种策略模式,Arrays.sort()里要求传入一种排序策略类型也是一种策略模式Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。
- 另外:我们一般处理这类避免大量分类的情况还可以用工厂模式,这俩的区别是一个是行为模式,一个是创建模式
- 工厂模式是属于创建型设计模式,主要用来针对不同类型创建不同的对象,达到解偶类对象。
- 策略模式是属于行为型设计模式,主要是针对不同的策略做出对应行为,达到行为解偶
作者:名字是乱打的
原文链接:https://www.jianshu.com/p/9cd303403270