策略枚举
枚举中定义各种策略名
public enum StrategyEnum {
FCFS("FCFS","先来先服务"),
SJF("SJF","短作业优先"),
HPF("HPF","高优先级优先");
private final String name;
private final String description;
public static StrategyEnum getByName(String name) {
return Arrays.stream(StrategyEnum.values())
.filter(e -> e.name.equals(name))
.findFirst().orElse(null);
}
StrategyEnum(String name, String description) {
this.name = name;
this.description = description;
}
}
策略注解
定义一个策略注解,用在各种策略的实现类上。
RetentionPolicy.RUNTIME:该注解需保留到运行时
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Strategy {
@NotNull
StrategyEnum value();
}
实现类接口
基于接口的模板模式,各种策略的实现类有不同的实现方法
public interface IHander {
String execute();
}
实现类示例
在实现类上加策略注解,指定对应的策略,并注入spring容器
@Service
@Strategy(StrategyEnum.FCFS)
public class FCFSHandler implements IHander{
@Override
public String execute() {
return "FCFSHandler:执行先来先服务策略";
}
}
spring容器代理类
实现了ApplicationContextAware接口,在容器初始化完成后会被调用,并初始化策略管理器
@Configuration
public class SpringContextProxy implements ApplicationContextAware {
/**
* 私有化容器,只能通过当前类提供的{@link #getBean}方法调用
*/
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// 先拿到spring容器
SpringContextProxy.applicationContext = applicationContext;
// 再初始化策略管理器
StrategyHandlerManager.init();
}
public static <T> T getBean(Class<T> requiredType){
return applicationContext.getBean(requiredType);
}
}
策略管理器(静态)
在策略管理器中使用一个Map,key:策略枚举,value:对应的实现类
public class StrategyHandlerManager {
// handlerMap:映射策略与处理类
private static Map<StrategyEnum, IHander> handerMap = new HashMap<>(StrategyEnum.values().length);
/**
* 初始化策略管理器
*/
public static void init() {
// 创建一个扫包器
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
// 添加注解过滤器
provider.addIncludeFilter(new AnnotationTypeFilter(Strategy.class));
// 扫包,获得结果集
Set<BeanDefinition> beanDefinitionSet = provider.findCandidateComponents("com.kaysen.handler");
// 遍历set
for (BeanDefinition beanDefinition : beanDefinitionSet) {
// 获取类名
String className = beanDefinition.getBeanClassName();
// 加载类
Class<?> clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
continue;
}
// 看该类有没有实现接口
Type ihandler = Arrays.stream(clazz.getGenericInterfaces()).filter(type -> type.equals(IHander.class)).findFirst().orElse(null);
// 该类肯定有Strategy注解
Strategy strategy = clazz.getAnnotation(Strategy.class);
// 获取value
StrategyEnum strategyEnum = strategy.value();
// 检查有没有指定value,以及有没有实现接口
if (strategyEnum == null || ihandler == null) {
continue;
}
// 指定了注解的value,且实现了接口,可以尝试从容器中获取(如果没有加@Service注解,容器中可能没有)
IHander handler = (IHander) SpringContextProxy.getBean(clazz);
// 找到了,加入map
handerMap.put(strategyEnum, handler);
// System.out.println(strategyEnum);
}
}
/**
* 根据策略获取handler
* @param strategyEnum 策略枚举
* @return IHander 对应的处理类
*/
public static IHander getHandler(StrategyEnum strategyEnum) {
return handerMap.get(strategyEnum);
}
}
如何使用
从策略管理器的map中获取对应的实现类,基于接口调用执行
@Service
public class StrategyService {
public String doStrategy(String strategyName){
StrategyEnum strategyEnum = StrategyEnum.getByName(strategyName);
if (strategyEnum == null) {
return "参数错误";
}
IHander handler = StrategyHandlerManager.getHandler(strategyEnum);
if (handler == null) {
return "找不到处理类";
}
return handler.execute();
}
}