【策略模式】策略模式结合Spring实战Demo
策略模式
策略模式用于解决判断分支过多的问题,使代码变得简洁和优雅,
策略模式在多种方式在项目中落地,下面举例说明通过指定不同类型的订单使用策略模式执行不同的业务逻辑
文章参考自公众号:石杉的架构笔记
一.项目结构
二.各个类的说明
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
【策略模式】策略模式结合Spring实战Demo的更多相关文章
- 【责任链模式】责任链模式结合Spring实战Demo
备注: 责任链与策略模式有很多相似之处,如都是行为型设计模式,都能够处理代码中的if-else逻辑 主要区别在于: 策略模式 封装了算法,通过上下文对象去接受客户端的数据,根据数据类型执行不同的算法 ...
- 《设计模式面试小炒》策略和工厂模式替代业务场景中复杂的ifelse
<设计模式面试小炒>策略和工厂模式替代业务场景中复杂的ifelse 我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统, ...
- 3.js模式-策略模式
1. 策略模式 策略模式定义一系列的算法,把它们封装起来,并且可以互相替换. var strategies = { isNonEmpty: function(value,errMsg){ if(val ...
- 模板模式与策略模式/template模式与strategy模式/行为型模式
模板模式 模版模式,又被称为模版方法模式,它可以将工作流程进行封装,并且对外提供了个性化的控制,但主流程外界不能修改,也就是说,模版方法模式中,将工作的主体架构规定好,具体类可以根据自己的需要,各自去 ...
- 命令模式 & 策略模式 & 模板方法
一.策略模式 策略模式:封装易变化的算法,可互相替换. GoF<设计模式>中说道:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换.该模式使得算法可独立于它们的客户变化. 比如 ...
- Java设计模式(七)策略模式 模板模式
(十三)策略模式 策略图案限定了多个封装算法,该算法可以相互替换包.法的客户.借用还有一位大神的样例. interface ICalculator{ public int calculate(Stri ...
- Springboot中实现策略模式+工厂模式
策略模式和工厂模式相信大家都比较熟悉,但是大家有没有在springboot中实现策略和工厂模式? 具体策略模式和工厂模式的UML我就不给出来了,使用这个这两个模式主要是防止程序中出现大量的IF ELS ...
- 工厂模式&策略模式。
抽象.封装,具体事情做得越多,越容易犯错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,犯错误可能性就越少.好象我们从编程序中也能悟出人生道理.(百度百科) 不断抽象封装 ...
- 简单工厂模式&策略模式-简介与区别
不得不说,这两种模式真的很像. 相似点:都用到了面向对象的继承.多态.抽象,都拥有相似的结构. 不同点:工厂模式仅提供具体的实例对象,怎么使用这个对象是client的自由,策略模式client可以通过 ...
随机推荐
- 死磕Spring之IoC篇 - Bean 的创建过程
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...
- Maven基础&&Spring框架阶段常用工具类整理
常用工具类 1.密码加密工具类: package com.itheima.utils; import java.security.MessageDigest; import sun.misc.BASE ...
- 微信小程序在Android和Ios端的获取时间兼容性问题
an端 var time = new Date() 例如:2020-01-01 01:01:00 ios端 var time = new Date() 例如:2020/01/01 01:01:00 ...
- Comet OJ - Contest #9 & X Round 3 【XR-3】核心城市 【树的理解】
一.题目 [XR-3]核心城市 二.分析 题意就是在树中确定$K$个点,满足剩下的$N-K$个点中到这$K$个点的最大距离尽可能小. 理解上肯定是确定一个根,这个根是这个图的中心. 可以通过根据结点的 ...
- golang 并发运算时主线程先运行完,子线程运行没结束的问题记录
代码如下: blocks,err:= mgo.FindBlocks(batch) //获得当前批次下的矿体信息 cubes:= BlockCutting(blocks[0],x,y,z,nest) f ...
- 程序员必须搞懂的20个Java类库和API
本文总结了日志.JSON解析.单测.XML解析.字节码处理.数据库连接池.集合类.邮件.加密.嵌入式SQL数据库.JDBC故障诊断以及序列化等20个方面的常用类库.都是你日常开发经常可能要用到的,现在 ...
- 3.DataFrame的增删改查
以此为例 一.DataFrame的初步认知 在pandas中完成数据读取后数据以DataFrame保存.在操作时要以DataFrame函数进行了解 函数 含义 示例 values 元素 index 索 ...
- effective解读-第一条 静态工厂创建对象代替构造器
好处 有名称,能见名知意.例如BigInteger的probablePrime方法 享元模式.单例模式中使用 享元模式:创建对象代价很高,重复调用已有对象,例如数据库连接等.享元模式是单例模式的一个拓 ...
- 【linux】系统编程-4-共享内存
目录 前言 6. 共享内存 6.1 概念 6.2 操作函数 6.2.1 shmget() 6.2.2 shmat() 6.2.3 shmdt() 6.2.4 shmctl() 6.3 例子 参考: 前 ...
- MongoDB教程--配置与入门
MongoDB简介 阿里云配置MongoDB 数据库的增删查改 MongoDB 数据最重要的操作是Key-Value的映射.有了这样的映射,可以直接通过关键字去寻找想要的值.例如,通过用户的ID寻找与 ...