阅读 111

策略模式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

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐