发送不同类型的消息----------策略模式

一:首先看下代码结构

发送不同类型的消息----------策略模式_第1张图片

annotation:注解

context:调度容器(会存放不同消息策略实现列表)

enums:不同消息类型的枚举

listener:springboot项目初始化的时候初始化消息策略实现与枚举类型的绑定关系并加入到调度容器里面

service:消息接口定义

impl:具体消息策略实现

 

二:具体代码讲解

 

1:消息类型枚举:
MsgTypeEnum.java

package com.sgl.designpattern.strategy.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @Author sgl
 * @Description 发送消息类型
 * @Date 2020/01/16 上午 10:13
 **/
@Getter
@AllArgsConstructor
public enum MsgTypeEnum {
	EMAIL_MSG(1, "邮件消息"),
	SHORT_MSG(2, "短信消息");
	private int index;
	private String description;

}

2:定义自定义注解(注解的value字段就是上面的枚举):

MsgTypeHandler
package com.sgl.designpattern.strategy.annotation;

import com.sgl.designpattern.strategy.enums.MsgTypeEnum;
import java.lang.annotation.*;

@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgTypeHandler {
    MsgTypeEnum value();
}

3:定义消息策略总接口:

MsgTypeService
package com.sgl.designpattern.strategy.service;


//策略接口
public interface MsgTypeService {

   void sendMsg(Object object);

}

4:定义不同消息策略实现

这两个实现策略都加了上面自定义注解,并且跟对应的消息类型枚举建立了绑定关系):

EmailMsgImpl(邮件消息)
/**
 * @Description: 邮件消息
 * @Author: sgl
 * @Date: 2020/1/17 上午 10:54
 */
@Service
@MsgTypeHandler(value = MsgTypeEnum.EMAIL_MSG)
public class EmailMsgImpl implements MsgTypeService{

    @Override
    public void sendMsg(Object object) {
        System.out.println("发送邮件消息....");
    }
}
ShortMsgImpl(短信消息)
/**
 * @Description: 短信消息
 * @Author: sgl
 * @Date: 2020/1/17 上午 10:54
 */
@Service
@MsgTypeHandler(value = MsgTypeEnum.SHORT_MSG)
public class ShortMsgImpl implements MsgTypeService {

    @Override
    public void sendMsg(Object object) {
        System.out.println("发送短信消息....");
    }
}

 

5:类型枚举策略映射管理容器(相当于工具,容器类)

SendMsgTypeContext
/**
 * @Description: 类型枚举策略映射管理容器
 * @Author: sgl
 * @Date: 2020/1/17 上午 11:49
 */
@Component
public class SendMsgTypeContext {

    private final Map handlerMap = new HashMap<>(8);

    public MsgTypeService getMessageService(Integer type) {
        return handlerMap.get(type);
    }

    public void putMessageService(Integer code, MsgTypeService conditionTypeService) {
        handlerMap.put(code, conditionTypeService);
    }

}

 

6:初始化所有消息类型枚举和策略映射的监听器

通过反射自定义注解把所有消息类型的绑定关系都初始化到上面的工具容器中

ConditionTypeListener
/**
 * @Description: 初始化所有消息类型枚举和策略映射
 * @Author: sgl
 * @Date: 2020/1/17 上午 11:47
 */
@Component
public class ConditionTypeListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        Map beans = event.getApplicationContext().getBeansWithAnnotation(MsgTypeHandler.class);
        SendMsgTypeContext conditionTypeContext = event.getApplicationContext().getBean(SendMsgTypeContext.class);
        beans.forEach((name, bean) -> {
            MsgTypeHandler typeHandler = bean.getClass().getAnnotation(MsgTypeHandler.class);
            conditionTypeContext.putMessageService(typeHandler.value().getIndex(), (MsgTypeService) bean);
        });
    }
}

 

7:单元测试效果

StrategyTests
@RunWith(SpringRunner.class)
@SpringBootTest
public class StrategyTests {
    @Resource
    private SendMsgTypeContext conditionTypeContext;

    //策略模式测试
    @Test
    public void contextLoads() {

        //这里直接取所有类型枚举测试
        MsgTypeEnum[] typeEnums = MsgTypeEnum.values();
        for (MsgTypeEnum typeEnum : typeEnums) {
            //可以根据不同的类型发送不同的消息
            MsgTypeService typeService = conditionTypeContext.getMessageService(typeEnum.getIndex());
            //实际开发中可以用来传参
            Object object = new Object();
            typeService.sendMsg(object);
        }


    }

}

发送不同类型的消息----------策略模式_第2张图片

 

注意:其实精华就在于用自定义注解的方式把策略实现类跟枚举类型一对一绑定上了,以及第6步里面通过自定义注解在项目初始化的时候把所有策略初始化到工具容器里面!

 

源码地址:https://github.com/Hak-L/designpattern.git

strategy这个目录!

发送不同类型的消息----------策略模式_第3张图片

你可能感兴趣的:(设计模式实战)