基于spring容器的策略模式+模板模式

策略枚举

枚举中定义各种策略名

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();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值