策略模式
策略模式用于解决判断分支过多的问题,使代码变得简洁和优雅,
策略模式在多种方式在项目中落地,下面举例说明通过指定不同类型的订单使用策略模式执行不同的业务逻辑
文章参考自公众号:石杉的架构笔记
一.项目结构

二.各个类的说明
1.自定义注解
//通过注解中的value值来表示不同的分支,从而执行不同的业务逻辑
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
String value();
}
2.处理器相关
-抽象处理器-定义子处理器要实现的行为
public abstract class AbstractHandler {
public abstract String handle(OrderDTO dto);
}
-子处理器1-实现抽相关处理器的行为1
@HandlerType(value = "1")
@Component
public class NomalHandler extends AbstractHandler{
@Override
public String handle(OrderDTO dto) {
return "normal";
}
}
-子处理器2-实现抽相关处理器的行为2
@HandlerType(value = "2")
@Component
public class GroupHandler extends AbstractHandler{
@Override
public String handle(OrderDTO dto) {
return "group";
}
}
-处理器上下文-根据不同条件映射到不同的处理器
public class HandleContext {
private Map<String,Class> handlerMap;
public HandleContext(Map<String,Class> handlerMap){
this.handlerMap=handlerMap;
}
public AbstractHandler getInstance(String type){
Class<? extends AbstractHandler> aClass = handlerMap.get(type);
if (aClass==null) {
throw new IllegalArgumentException();
}
return SpringContextUtil.getBean(aClass);
}
}
3.处理器加载类-用于加载处理器上下文到spring的bean容器中,同时初始化数据
@Component
@SuppressWarnings("unchecked")
public class HandlerProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<String, Class> handlerMap = new HashMap<>();
//获取指定报下的所有类
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metaReader = new CachingMetadataReaderFactory();
List<Class<?>> list = new ArrayList();
try {
Resource[] resources = resolver.getResources("classpath*:designstrategy/demo/config/handler/*.class");
ClassLoader loader = ClassLoader.getSystemClassLoader();
for (Resource resource : resources) {
MetadataReader reader = metaReader.getMetadataReader(resource);
String className = reader.getClassMetadata().getClassName();
Class<?> clazz = loader.loadClass(className);
HandlerType annotation = clazz.getAnnotation(HandlerType.class);
// System.out.println("格式化前:"+clazz); class designstrategy.demo.config.handler.AbstractHandler
System.err.println("格式化后:" + ClassUtils.getQualifiedName(clazz));
//获取所有接口
ClassUtils.getAllInterfaces(clazz);
//判断是一个类是不是抽象类
boolean anAbstract = Modifier.isAbstract(clazz.getModifiers());
// System.err.println("判断一个类是不是抽象类:" + anAbstract);如果不是抽象类,添加到集合
if (!anAbstract) {
list.add(clazz);
}
}
System.out.println("集合" + list);
//将类添加到Map中
for (Class<?> aClass : list) {
Annotation[] annotations = aClass.getAnnotations();
// 这里有个坑 Annotation annotation = aClass.getAnnotation(HandlerType.class);获取到的annotation为null
for (Annotation annotation : annotations) {
if (annotation instanceof HandlerType) {
String value = ((HandlerType) annotation).value();
handlerMap.put(value, aClass);
System.out.println(value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
HandleContext handleContext = new HandleContext(handlerMap);
//将上下文添加到spring bean容器中
configurableListableBeanFactory.registerSingleton(HandleContext.class.getName(), handleContext);
}
}
4.工具类-用于获取spring 容器中的bean
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
5.controller层
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/handle")
public String handle(OrderDTO dto){
String str=orderService.handle(dto);
System.out.println(str);
return str;
}
}
6.service层
@Service
public class OrderServiceImpl implements OrderService{
@Autowired
private HandleContext handleContext;
@Override
public String handle(OrderDTO dto) {
AbstractHandler handler = handleContext.getInstance(dto.getType());
return handler.handle(dto);
}
}
7.实体
@Data
public class OrderDTO {
/** 订单类型 */
private String type;
}
三.测试
启动项目:使用postman分别测试以下两个接口
接口一:localhost:8080/order/hander?type=1
返回结果:normal
接口二localhost:8080/order/hander?type=2
返回结果:group
代码地址:https://github.com/AlenYang123456/design-strategy