首页 > 其他分享 >Spring项目中策略模式使用

Spring项目中策略模式使用

时间:2023-07-17 18:34:15浏览次数:54  
标签:MAP 策略 service Spring 模式 STRATEGY message public

一、策略模式定义

策略模式(Strategy Pattern)是行为型策略模式当中的一种,定义一系列算法,将每个算法封装到具有公共接口的一系列策略类中,(可以是抽象类,也可以是接口),从而使他们可以相互替换,让算法可在不影响客户端的情况下发生变化,
作用:
将算法的责任和本身进行解耦,使得:
1、算法可独立于使用外部而变化
2、客户端方便根据外部条件选择不同的策略来解决不同的问题
定义策略接口:

public interface EventStrategy<T extends Message> {

    /**
     * 处理事件消息
     * @param Message
     * @return
     */
     boolean handleMessage(T Message);
}

二、实现

具体策略实现类:

UML图如下:
这里比如说有一个需要发送消息通知的队列,可能需要发到微信,也可能需要发到飞书,各个平台的api不一样,所以单独采用一个策略实现

像之前的项目注册到策略都采用new 对象的方式,这里因为是spring项目,依赖于DI,所以自动注入到Context当中,不需要我们手动操作

@Slf4j
@Service
public class EventContext {

    private static Map<String, EventStrategy> STRATEGY_MAP = new HashMap<>(16);

    public EventContext(List<EventStrategy> messageServices) {
        messageServices.forEach(service ->
                service.getMessageTypes().forEach(type ->  STRATEGY_MAP.put((String) type, service)));
    }

    public boolean consumeEventMessage(Message message) {
        STRATEGY_MAP.get(message.getType()).handleMessage(message);
        return true;
    }
}

注入到STRATEGY_MAP的方法很多,如果是非spring的项目可能需要将每一个实现类手动添加进去

这里使用的是构造器注入
也可以实现ApplicationContextAware

public class EventContext implements ApplicationContextAware {

    private static Map<String, EventStrategy> STRATEGY_MAP = new HashMap<>(16);

    public boolean consumeEventMessage(Message message) {
        STRATEGY_MAP.get(message.getType()).handleMessage(message);
        return true;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, EventStrategy> beanMap = applicationContext.getBeansOfType(EventStrategy.class);
        beanMap.forEach((name, service) -> {
            STRATEGY_MAP.put(service.getMessageType(), service);
        });
    }
}

当然也可以实现InitializingBean

这里使用构造器注入更简洁,也符合spring的设计理念

三、扩展:

这里假如可能有两种平台的消息通知是一样的,消息type是163mali和QQmail都属于邮件类型消息通知,当它们共用一个策略时,可以在接口定义抽象方法,全部注册到STRATEGY_MAP
举例说明:


可以看到成功注入进去,
这里策略上下文的key值一般是由枚举定义,

修改接口方法的类型与实现类

最后修改如下

这里上下文可能更多的是返回具体的实现类,来实现不同的逻辑

新建测试类,可以看到最终效果

四、总结

优点:
1、依赖Spring的DI,简化了手动创建策略类实例的过程
2、调用方无需知道具体的策略实现逻辑,可以干掉多重if else, 降低模块间的耦合
3、方便扩展,如果有新的类型,只需要实现接口类并交注入到spring交给容器处理即可,符合开闭原则
缺点:
1、使用不当可能会造成策略实现类臃肿
如果条件不是很多,尽量使用if else,如果确定具体的算法不会变,一两个这种,没有必要滥用设计模式,代码是一步一步优化出来的,不是一步到位实现的。大于三个可以使用卫语句,考虑策略模式来简化代码。

标签:MAP,策略,service,Spring,模式,STRATEGY,message,public
From: https://www.cnblogs.com/LiuFqiang/p/17560871.html

相关文章

  • SpringMVC文件上传
    相关依赖使用SpringMVC提供的文件上传需要在项目中加入两个jar包,对应的maven的依赖分别是:commons-io和commons-fileupload<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dep......
  • spring中的bean对象的有关了解
    @ConfigurationpublicclassAppConfig{@BeanpublicMyBeangetMyBean(){MyBeanmyBean=newMyBean();myBean.setName("Example");returnmyBean;}//其他的@Bean方法...}上述是一个配置类,里面有个@Bean注解修饰,@Configuration注解的类......
  • springboot相较之前ssm有什么区别和优势
    1、快速可搭建的脚手架,少量配置,约定优于配置,不用像ssm那样增加复杂的配置文件2、这种方式使程序员更加集中于业务代码的编写,而不用关注部署和容器配置的问题3、约定优于配置也不是任何场景都适用,主要还是免去了servlet的配置4、内置tomcat直接启动......
  • Spring 整合Redis
    1.配置application.ymlspring:application:name:meter-highwayprofiles:active:druid,mongodb,dubbo,rabbitmq,redisapplication-redis.ymlspring:redis:database:9host:192.168.13.146port:6379password:Luban376timeout:20002.依赖<dependency>......
  • spring启动流程 (5) Autowired原理
    构造方法参数AutowireBeanClass可以在构造方法上标注@Autowired注解,Spring在创建Bean实例时将自动为其注入依赖参数Spring会优先使用标注@Autowired注解的构造方法当一个构造方法标注了@Autowired注解且required=true时,其余构造方法不允许再标注@Autowired注解当多个构造方法......
  • mongodb副本集(PSA模式)修改节点信息
    环境:OS:Centos7mongodb:4.4.22 我们在副本集扩容的情况下,新加入节点一般设置priority和votes都为0,待新节点数据同步完成后再进行修改:主库上执行新增新的节点:myrepl:PRIMARY>rs.add({host:"192.168.1.107:29001",priority:0,votes:0})待同步完成后查看副本集配置 ......
  • 【进阶玩法】策略+责任链+组合实现合同签章
    前置内容掌握策略模式掌握责任链模式掌握类继承、接口的实现掌握参数的传递与设置GitHub地址ps:【文章由来】公司项目中所用的合同签章处理流程,本人基于责任链上使用策略模式进行优化。签章的处理流程合同文本初始化合同文本生成签章挡板是否开启合同签章发送mq合同......
  • JVM专栏-内存分配与回收策略
    对象的内存分配,就是在堆上分配(也可能经过JIT编译后被拆散为标量类型并间接在栈上分配),对象主要分配在新生代的Eden区上,少数情况下可能直接分配在老年代,分配规则不固定,取决于当前使用的垃圾收集器组合以及相关的参数配置。以下列举几条最普遍的内存分配规则,供大家学习。对象优......
  • Spring
    1.注解 @Value使用在字段或方法上,用于注入普通数据 一般用于注入配置信息 @Autowired使用在字段或方法上,用于根据类型注入引用数据 @Qualifier使用在字段或方法上,结合@Autowired,根据名称注入 @Resource使用在字段或方法上,根据类型或名称进行注入2.spring的其......
  • springboot中静态资源的访问相关知识
    一、基本介绍:(一)、只要静态资源放在类路径下(什么是类路径:在resources文件下)默认是这几个目录文件:/static、/public、/resources、/META-INF/resources等目录下的文件直接能够被访问(二)、常见的静态资源:Js、css、图片(jbg、png、svg、gif、bmp)、字体文件(fonts)等(三)、访问方式:......