源码meethigher/springboot-strategy-mode
参考文章
SpringBoot下的策略模式,消灭了大量的ifelse,真香!_程序新视界-CSDN博客
springboot基于注解方式实现策略模式_aogula的博客-CSDN博客,主要抄袭自这篇文章
适配器模式和策略模式 - 知乎
@SuppressWarnings注解常见用法_小楼夜听雨的博客-CSDN博客
还是来自于工作上的一点心得。之前我做的数据库的通用调用存储过程的代码,是使用抽象工厂来实现的,里面有if..else..的操作。如果要频繁的新加数据库实现逻辑,就要不断的添加实现类和else if。这边就想用注解的方式,来去除if..else..
案例:发送不同类型的消息
创建注解
@Target({ElementType.TYPE})//作用在类上 @Retention(RetentionPolicy.RUNTIME)//当前被描述的注解,会保留到class字节码文件中,并被jvm读取到。一般也只会用到这个 @Documented//注解被抽取到api文档中 @Inherited//注解被子类继承 public @interface MsgType { MessageType value(); }
创建类型
public enum MessageType { /** * 微信· */ WECHAT_MSG, /** * 短信 */ SMS_MSG }
创建接口
public interface MessageHandler { /** * 发送消息 * @param msg */ String sendMessage(String msg); }
创建SMS实现类
@Service @MsgType(value = MessageType.SMS_MSG) public class SmsMessageHandler implements MessageHandler { @Override public String sendMessage(String msg) { String message = "短信消息:" + msg; System.out.println(message); return message; } }
创建WECHAT实现类
@Service @MsgType(value = MessageType.WECHAT_MSG) public class WechatMessageHandler implements MessageHandler { @Override public String sendMessage(String msg) { String message = "微信消息:" + msg; System.out.println(message); return message; } }
创建配置类
@Component public class MessageConfig implements ApplicationContextAware { private static Map<MessageType, Class<MessageHandler>> messageTypeClassMap = new HashMap<>(); @Autowired private ApplicationContext applicationContext; /** * 1. 通过注解拿到所有被标注的bean类 * 2. 遍历所有bean,拿到bean的类型、字节码 * 3. 将类型、字节码存入全局map * 4. 使用时,通过类型,将字节码取出,instance或者通过spring放入bean容器 * * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //比较平易近人的写法 Map<String, Object> beans = applicationContext.getBeansWithAnnotation(MsgType.class); Iterator<String> iterator = beans.keySet().iterator(); while (iterator.hasNext()) { String beanName = iterator.next(); @SuppressWarnings("unchecked") Class<MessageHandler> messageHandlerClass = (Class<MessageHandler>) beans.get(beanName).getClass(); MessageType messageType = messageHandlerClass.getAnnotation(MsgType.class).value(); messageTypeClassMap.put(messageType, messageHandlerClass); } //比较装逼的写法 // //获取所有带有指定注解的Bean对象 // applicationContext.getBeansWithAnnotation(MsgType.class) // .entrySet() // .iterator() // .forEachRemaining(stringObjectEntry -> { // Class<MessageHandler> messageHandlerClass = (Class<MessageHandler>) stringObjectEntry.getValue().getClass(); // MessageType messageType = messageHandlerClass.getAnnotation(MsgType.class).value(); // messageTypeClassMap.put(messageType, messageHandlerClass); // }); } /** * 通过类型拿到实例化的对象 * @param messageType * @return */ public MessageHandler getMessageHandler(MessageType messageType) { Class<MessageHandler> messageHandlerClass = messageTypeClassMap.get(messageType); if (ObjectUtils.isEmpty(messageHandlerClass)) { throw new IllegalArgumentException("没有指定类型"); } return applicationContext.getBean(messageHandlerClass); } }
案例:根据频次来进行工作,频次有,一天一次,三天一次,七天一次,十天一次
创建枚举
public enum WorkFrequency { /** * 一天一次 */ ONE_DAY_PER_TIMES("1天/次", "0", "oneDayPerTimes"), /** * 三天一次 */ THREE_DAY_PER_TIMES("3天/次", "1", "threeDayPerTimes"), /** * 七天一次 */ SEVEN_DAY_PER_TIMES("7天/次", "2", "sevenDayPerTimes"), /** * 十天一次 */ TEN_DAY_PER_TIMES("10天/次", "3", "tenDayPerTimes"), ; public final String name; public final String value; public final String uniqueCode; WorkFrequency(String name, String value, String uniqueCode) { this.name = name; this.value = value; this.uniqueCode = uniqueCode; } public static WorkFrequency getByUniqueCode(String uniqueCode) { for (WorkFrequency frequency : WorkFrequency.values()) { if (frequency.uniqueCode.equals(uniqueCode)) { return frequency; } } return null; } }
创建注解
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface FrequencyAnnotation { WorkFrequency value(); }
创建接口
public interface WorkFrequencyHandler { /** * 今天是否应该执行 * * @param lastExecuteTime * @return */ boolean isTodayShouldExecute(Long lastExecuteTime); }
创建实现类
public class WorkTimeUtils { /** * 两个时间相差天数 * * @param startTime Date日期 * @param endTime Date日期 * @return */ public static int intervalDays(Date startTime, Date endTime) { Calendar cal1 = Calendar.getInstance(); cal1.setTime(startTime); Calendar cal2 = Calendar.getInstance(); cal2.setTime(endTime); int day1 = cal1.get(Calendar.DAY_OF_YEAR); int day2 = cal2.get(Calendar.DAY_OF_YEAR); int year1 = cal1.get(Calendar.YEAR); int year2 = cal2.get(Calendar.YEAR); /*同一年 */ if (year1 != year2) { int timeDistance = 0; for (int i = year1; i < year2; i++) { if ((((i % 4) == 0) && ((i % 100) != 0)) || ((i % 400) == 0)) { /* 闰年 */ timeDistance += 366; } else { /*不是闰年 */ timeDistance += 365; } } return (timeDistance + (day2 - day1)); } else { /*不同年 */ return (day2 - day1); } } } @Service @FrequencyAnnotation(value = WorkFrequency.ONE_DAY_PER_TIMES) public class OneDayOnceHandler implements WorkFrequencyHandler { /** * 间隔的天数 */ private final Integer INTERVAL_DAY = 1; @Override public boolean isTodayShouldExecute(Long lastExecuteTime) { long currentTimeMillis = System.currentTimeMillis(); int realIntervalDay = WorkTimeUtils.intervalDays(lastExecuteTime, currentTimeMillis); if (realIntervalDay >= INTERVAL_DAY) { return true; } else { return false; } } } @Service @FrequencyAnnotation(value = WorkFrequency.THREE_DAY_PER_TIMES) public class ThreeDayOnceHandler implements WorkFrequencyHandler { /** * 间隔的天数 */ private final Integer INTERVAL_DAY = 3; @Override public boolean isTodayShouldExecute(Long lastExecuteTime) { long currentTimeMillis = System.currentTimeMillis(); int realIntervalDay = WorkTimeUtils.intervalDays(lastExecuteTime, currentTimeMillis); if (realIntervalDay >= INTERVAL_DAY) { return true; } else { return false; } } } @Service @FrequencyAnnotation(value = WorkFrequency.SEVEN_DAY_PER_TIMES) public class SevenDayOnceHandler implements WorkFrequencyHandler { /** * 间隔的天数 */ private final Integer INTERVAL_DAY = 7; @Override public boolean isTodayShouldExecute(Long lastExecuteTime) { long currentTimeMillis = System.currentTimeMillis(); int realIntervalDay = WorkTimeUtils.intervalDays(lastExecuteTime, currentTimeMillis); if (realIntervalDay >= INTERVAL_DAY) { return true; } else { return false; } } } @Service @FrequencyAnnotation(value = WorkFrequency.TEN_DAY_PER_TIMES) public class TenDayOnceHandler implements WorkFrequencyHandler { /** * 间隔的天数 */ private final Integer INTERVAL_DAY = 10; @Override public boolean isTodayShouldExecute(Long lastExecuteTime) { long currentTimeMillis = System.currentTimeMillis(); int realIntervalDay = WorkTimeUtils.intervalDays(lastExecuteTime, currentTimeMillis); if (realIntervalDay >= INTERVAL_DAY) { return true; } else { return false; } } }
添加配置类,通过配置类,直接获取Service
@Configuration public class WorkFrequencyConfig implements ApplicationContextAware { /** * 存储对应关系 */ private static Map<WorkFrequency, Class<WorkFrequencyHandler>> workFrequencyClassMap = new HashMap<>(); @Autowired private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { applicationContext.getBeansWithAnnotation(FrequencyAnnotation.class) .entrySet() .iterator() .forEachRemaining(stringObjectEntry -> { Class<WorkFrequencyHandler> aClass = (Class<WorkFrequencyHandler>) stringObjectEntry.getValue().getClass(); WorkFrequency messageType = aClass.getAnnotation(FrequencyAnnotation.class).value(); workFrequencyClassMap.put(messageType, aClass); }); } /** * 通过类型拿到实例化的对象 * * @param messageType * @return */ public WorkFrequencyHandler getFrequencyHandler(WorkFrequency messageType) { Class<WorkFrequencyHandler> workFrequencyHandlerClass = workFrequencyClassMap.get(messageType); if (ObjectUtils.isEmpty(workFrequencyHandlerClass)) { throw new IllegalArgumentException("没有指定类型"); } return applicationContext.getBean(workFrequencyHandlerClass); } }
所有的配置好了,开始使用了。
@SpringBootTest public class WorkTest { @Autowired private WorkFrequencyConfig workFrequencyConfig; @Test public void test() { //模拟 People people = new People(); WorkFrequency workFrequency = WorkFrequency.getByUniqueCode(people.getFrequency()); WorkFrequencyHandler handler = workFrequencyConfig.getFrequencyHandler(workFrequency); boolean todayShouldExecute = handler.isTodayShouldExecute(people.getLastWorkTime()); if(todayShouldExecute) { System.out.println("今天应该工作"); }else { System.out.println("今天不应该工作"); } } static class People { private String frequency; private Long lastWorkTime; public People() { //模拟 this.frequency = "oneDayPerTimes"; this.lastWorkTime = System.currentTimeMillis(); } public String getFrequency() { return frequency; } public void setFrequency(String frequency) { this.frequency = frequency; } public Long getLastWorkTime() { return lastWorkTime; } public void setLastWorkTime(Long lastWorkTime) { this.lastWorkTime = lastWorkTime; } } }