springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改
前言 思路与模拟业务
源码地址 https://gitee.com/houzheng1216/springboot
整体思路就是通过注解在策略类上指定约定好的type,项目启动之后将所有有注解的type获取到,根据type存储,然后在业务中根据type获取对应的策略即可
模拟订单业务,根据订单的type,需要不同的处理逻辑,比如,免费订单,半价订单等,下面是项目结构:

一 策略接口和实现
/**
* 处理订单策略
*/
public interface OrderStrategy { void handleOrder(Order order);
}
@Component
@HandlerOrderType(Order.FREE) //使用注解标明策略类型
public class FreeOrderStrategy implements OrderStrategy {
@Override
public void handleOrder(Order order) {
System.out.println("----处理免费订单----");
}
}
@Component
@HandlerOrderType(Order.HALF)
public class HalfOrderStrategy implements OrderStrategy {
@Override
public void handleOrder(Order order) {
System.out.println("----处理半价订单----");
}
}
@Component
@HandlerOrderType(Order.DISCOUT)
public class DiscoutOrderStrategy implements OrderStrategy {
@Override
public void handleOrder(Order order) {
System.out.println("----处理打折订单----");
}
}
二 自定义策略注解
@Target(ElementType.TYPE) //作用在类上
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited //子类可以继承此注解
public @interface HandlerOrderType {
/**
* 策略类型
* @return
*/
int value();
}
此处只能用基本类型或者String,约定的类型放在Order实体类里
三 业务实体
public class Order {
public static final int FREE=1; //免费订单
public static final int HALF=2; //半价订单
public static final int DISCOUT=3; //打折订单
private String name;
private Double price;
private Integer type;//订单类型
public static Order build(){
return new Order();
}
四 核心功能实现
主要就是这一块实现策略逻辑
/**
* 根据订单类型返回对应的处理策略
*/
@Component
public class HandlerOrderContext {
@Autowired
private ApplicationContext applicationContext;
//存放所有策略类Bean的map
public static Map<Integer, Class<OrderStrategy>> orderStrategyBeanMap= new HashMap<>(); public OrderStrategy getOrderStrategy(Integer type){
Class<OrderStrategy> strategyClass = orderStrategyBeanMap.get(type);
if(strategyClass==null) throw new IllegalArgumentException("没有对应的订单类型");
//从容器中获取对应的策略Bean
return applicationContext.getBean(strategyClass);
}
}
/**
* 策略核心功能,获取所有策略注解的类型
* 并将对应的class初始化到HandlerOrderContext中
*/
@Component
public class HandlerOrderProcessor implements ApplicationContextAware {
/**
* 获取所有的策略Beanclass 加入HandlerOrderContext属性中
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取所有策略注解的Bean
Map<String, Object> orderStrategyMap = applicationContext.getBeansWithAnnotation(HandlerOrderType.class);
orderStrategyMap.forEach((k,v)->{
Class<OrderStrategy> orderStrategyClass = (Class<OrderStrategy>) v.getClass();
int type = orderStrategyClass.getAnnotation(HandlerOrderType.class).value();
//将class加入map中,type作为key
HandlerOrderContext.orderStrategyBeanMap.put(type,orderStrategyClass);
});
}
}
五 业务service使用
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
HandlerOrderContext handlerOrderContext;
@Override
public void handleOrder(Order order) {
//使用策略处理订单
OrderStrategy orderStrategy = handlerOrderContext.getOrderStrategy(order.getType());
orderStrategy.handleOrder(order);
}
}
很简单,业务代码以后基本不用再修改,不管添加多少策略或者需求变更多少次
六 controller测试
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
OrderService orderService;
@GetMapping("/handler/{type}")
public void handleOrder(@PathVariable Integer type){
Order order = Order.build()
.add("name", "微信订单")
.add("price", 99.9)
.add("type", type);
orderService.handleOrder(order);
}
}
使用链式风格构造对象
测试:

再添加策略添加实现类,启用注解即可!
省去了工厂模式,直接用注解实现,避免修改工厂类,
这里贴一个我们之前项目的工厂类实现:

如果再添加策略还是会有轻微的改动!
springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改的更多相关文章
- Springboot中如何自定义注解以及使用2例
不说废话,直接进入正题: java自定义注解主要有3步:1.编写@interface接口2.编写@interface对应的处理方法进行处理3.调用处理方法 示例一:判断奇偶:比如有一个字段no要判断奇 ...
- springboot中的常用注解
springboot中的常用注解个人觉得springboor中常用的注解主要可以分为三种:放入容器型注解.从容器中取出型注解和功能型注解.其中的放入容器型和从容器中取出型就是我们平时所说的控制反转和依 ...
- springboot中的controller注解没有生效
springboot中的controller注解没有生效 , 启动的Application类没有在controller的父目录或同级目录
- Java中的GOF23(23中设计模式)--------- 工厂模式(Factory)
Java中的GOF23(23中设计模式)--------- 工厂模式(Factory) 在给大家介绍工厂模式之前,我想和大家聊聊面向对象的那点事,在这里,引入三个概念. 开闭原则(Open Close ...
- python 使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件
1.使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件. 2.模板模式的目的:能保证快速开发各种邮箱客户端,子类只需要重写模板类邮箱的抽象方法即可.之后再开发任何邮箱就只要加一个类,写3行代码 ...
- javascript模式 (3)——工厂模式和装饰模式
上节我们讲解了单例模式,这节我们将继续讲解工厂模式和迭代器模式 工厂模式: 工厂模式的目的是为了方便的创建对象(可以在不知道构造的情况下),通过静态方法来实现,在java或c#等静态编译语言中需要通过 ...
- 结合实例分析简单工厂模式&工厂方法模式&抽象工厂模式的区别
之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个 ...
- 简单工厂模式,工厂方法模式,抽象工厂模式,spring的狂想
菜鸟D在项目中遇见一个比较纠结的高耦合,所以就想办法来解耦.情况是这样的:系统通过用户选择treeview控件的节点判断调用不同的处理,这些处理中某些东西又是类似的.同事的建议是采用简单工厂,耦合就耦 ...
- Java设计模式之(工厂模式)--简单工厂模式--工厂方法模式--抽象工厂模式
工厂模式: 工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 简单工厂模 ...
随机推荐
- 记springboot + MP +Hikari动态数据源配置
环境准备: springboot 2.1.6 mybatis-plus 数据库驱动 boot 自带hikari驱动 步骤1: 导入多数据源启动工具类 <!-- 多数据源支持 -->< ...
- 如何从0到1设计一个MQ消息队列
消息队列作为系统解耦,流量控制的利器,成为分布式系统核心组件之一. 如果你对消息队列背后的实现原理关注不多,其实了解消息队列背后的实现非常重要. 不仅知其然还要知其所以然,这才是一个优秀的工程师需要具 ...
- 机器学习之路--Pandas
Pandas 是对numpy的封装 Pandas 核心结构DataFrame 近似看出矩阵结构panda字符型叫object dataframe其中一行或者一列叫series dataframe 里面 ...
- 1049 数列的片段和 (20 分)C语言
给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) ...
- PHP 经典面试题集
这篇文章介绍的内容是关于PHP 经典面试题集 PHP 经典面试题集,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 结合我自己面试情况,面对的一些php面试题列举出来,基本上结合自己的看 ...
- 阿里云函数计算 .NET Core 初体验
体验了一波阿里云函数计算, 已支持 .NET Core 2.1, 那么按照惯例, 来写个 "Hello World" 吧. 作者注: 开发环境 Windows 10 & V ...
- Fabric1.4:Go 链码开发与编写
1 链码结构 1.1 链码接口 链码启动必须通过调用 shim 包中的 Start 函数,传递一个类型为 Chaincode 的参数,该参数是一个接口类型,有两个重要的函数 Init 与 Invoke ...
- 前端笔记5-js1
一.在JS中一共有6种数据类型1. String 字符串2. Number 数值3. Boolean 布尔值4. Null 空值5. Undefined 未定义6. Object 对象 其中 Stri ...
- python爬虫——scrapy的使用
本文中的知识点: 安装scrapy scrapy的基础教程 scrapy使用代理 安装scrapy 由于小哥的系统是win7,所以以下的演示是基于windows系统.linux系统的话,其实命令都一样 ...
- Oracle Autonomous Health Framework (AHF) 解读
AHF介绍 Oracle在2019年10月18日发布自治健康框架Autonomous Health Framework (AHF) 19.3,将ORAchk,EXAchk,TFA三种诊断工具合并入AH ...