前言 思路与模拟业务

源码地址 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,实现新增策略代码零修改的更多相关文章

  1. Springboot中如何自定义注解以及使用2例

    不说废话,直接进入正题: java自定义注解主要有3步:1.编写@interface接口2.编写@interface对应的处理方法进行处理3.调用处理方法 示例一:判断奇偶:比如有一个字段no要判断奇 ...

  2. springboot中的常用注解

    springboot中的常用注解个人觉得springboor中常用的注解主要可以分为三种:放入容器型注解.从容器中取出型注解和功能型注解.其中的放入容器型和从容器中取出型就是我们平时所说的控制反转和依 ...

  3. springboot中的controller注解没有生效

    springboot中的controller注解没有生效  , 启动的Application类没有在controller的父目录或同级目录

  4. Java中的GOF23(23中设计模式)--------- 工厂模式(Factory)

    Java中的GOF23(23中设计模式)--------- 工厂模式(Factory) 在给大家介绍工厂模式之前,我想和大家聊聊面向对象的那点事,在这里,引入三个概念. 开闭原则(Open Close ...

  5. python 使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件

    1.使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件. 2.模板模式的目的:能保证快速开发各种邮箱客户端,子类只需要重写模板类邮箱的抽象方法即可.之后再开发任何邮箱就只要加一个类,写3行代码 ...

  6. javascript模式 (3)——工厂模式和装饰模式

    上节我们讲解了单例模式,这节我们将继续讲解工厂模式和迭代器模式 工厂模式: 工厂模式的目的是为了方便的创建对象(可以在不知道构造的情况下),通过静态方法来实现,在java或c#等静态编译语言中需要通过 ...

  7. 结合实例分析简单工厂模式&工厂方法模式&抽象工厂模式的区别

    之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略.这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个 ...

  8. 简单工厂模式,工厂方法模式,抽象工厂模式,spring的狂想

    菜鸟D在项目中遇见一个比较纠结的高耦合,所以就想办法来解耦.情况是这样的:系统通过用户选择treeview控件的节点判断调用不同的处理,这些处理中某些东西又是类似的.同事的建议是采用简单工厂,耦合就耦 ...

  9. Java设计模式之(工厂模式)--简单工厂模式--工厂方法模式--抽象工厂模式

    工厂模式: 工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 简单工厂模 ...

随机推荐

  1. 如何基于TencentOS tiny,快速打造属于自己的IoT小应用?

    导语 | 近日,云+社区技术沙龙“腾讯开源技术”圆满落幕.本次沙龙邀请了多位腾讯技术专家,围绕腾讯开源与众多开发者进行探讨,深度揭秘了腾讯开源项目TencentOS tiny.TubeMQ.Kona  ...

  2. saltstack操作

    使用分组 修改minon的ID,做一个标识 [root@node2 ~]# vim /etc/salt/minionmaster: 172.25.254.130 id: web1 #node2[roo ...

  3. 使用svndumpfilter exclude来清理svn库的废弃文件实现差别备份

      先啰嗦下为什么要使用svndumpfilter… svn库用久了以后就会越来越大,进行整体文件打包备份的时候,发现压力山大…尤其是美术团队也在使用svn进行重要美术资源管理的时候…….几百g的资源 ...

  4. 从零开始のcocos2dx生活(九)CCBReader

    NodeLoaderLibrary是用来存储节点加载器类型的类,通过registerDefaultNodeLoaders()可以注册所有默认类型的加载器 在CocosBuilder的使用手册中: 1. ...

  5. win设置C、D、E等盘符图标为自定义的图片

    1.选择一张jpg图片,在下面网站工具上,转为ico的图片(最好转64x64的清晰些). http://www.faviconico.org/favicon 2.在D盘下新建文本文件.txt,写入以下 ...

  6. 小小知识点(三十八)MPSK和MQAM调制的实现——利用IQ调制

    IQ调制的原理 (一)调制基本原理 (二)调制基本原理 利用IQ调制实现MPSK(QPSK 8PSK BPSK)和MQAM(16QAM 64QAM)调制     (一)利用IQ调制实现QPSK调制   ...

  7. Groovy重载操作符

    重载一时爽,一直重载一直爽. 最近在读<Groovy in action>一本书重新复习了Groovy的一些语法特性,迷恋上这个重载操作符的功能,坚持爽的不要要的.分享一个Demo. 由于 ...

  8. spring-boot第一章:快速开始

    快速开始 创建pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns= ...

  9. doc_values VS stored field

    doc_values 按列存储,按docId排序,在query阶段使用,直接根据docId获取具体field的value,用来排序,聚合等. stored field按文档存储,按docId排序,一条 ...

  10. MySQL数据库(五)插入操作

    前提要述:参考书籍<MySQL必知必会> <MySQL必知必会>是先讲了查询,但是没有记录就无法查询,所以先将如何添加数据. 表已经知道怎么创建了,随便创两张. 5.1 插入数 ...