【策略模式】策略模式结合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可以通过 ...
随机推荐
- vue3使用路由
下载 npm install vue-router@4 配置路由 暴露出一个createRouter方法,用来创建路由对象 通过defineAsyncComponent方法来实现路由的懒加载(文章1. ...
- 剑指 Offer 10- II. 青蛙跳台阶问题
剑指 Offer 10- II. 青蛙跳台阶问题 Offer 10- II 题目描述: 动态规划方程: 循环求余: 复杂度分析: package com.walegarrett.offer; impo ...
- 五十:代码审计-PHP无框架项目SQL注入挖掘技巧
代码审计教学计划: 审计项目漏洞Demo->审计思路->完整源码框架->验证并利用漏洞 代码审计教学内容: PHP,JAVA网站应用,引入框架类开发源码,相关审计工具及插件使用 代码 ...
- Java 并发编程小册整理好了
Java 有并发,并发知识之大,一口吃不下 这曾是我不愿意触碰的知识角 多次一头扎进并发,无功而返 为应对面试,临时苦苦记忆,不成体系 这一次我决定从基础开始,攻克它 12,0000 字 68Mb 高 ...
- Maven配置ali镜像
Maven目录,Conf文件夹下settings.xml 找到mirrors节点 添加配置 <mirror> <id>alimaven</id> <mirro ...
- SQL练习——LeetCode解题和总结(2)
602. Friend Requests II: Who Has the Most Friends[M] 一.表信息 In social network like Facebook or Twitte ...
- MySQL入门(4)——操作数据表
MySQL入门(4)--操作数据表 创建数据库 CREATE [TEMPORARY] TABLE [IF NOT EXISTS] 数据库名 [(create_definition,...)] [tab ...
- Mardown语法
1.什么是Markdown Mardown是一种文本标记语言,使用它,能让我们更加专注于内容的输出,而不是排版样式. 我们平常使用的.txt文档书写的文字是没有样式的,使用Markdown语法就可以给 ...
- 1-认识c指针
1.指针和内存 c程序在编译后,会以三种形式使用内存 1静态/全局内存 静态声明的变量分配在这里,全局变量也使用这部分内存.这些变量在程序开始运行时分配,直到程序终止时才会消失 2.自动内存 这些变量 ...
- sqli-labs系列——第一关
先看了一遍关于sql的一些知识点,通关sqli-labs加深下印象.之前也因为作业的原因通关过前10关,但那时候不懂得原理,跟着网上的教程做的,所以这次尝试自己思考通关. less1 尝试and1=2 ...