springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改...

前言 思路与模拟业务

源码地址 https://gitee.com/houzheng1216/springboot

整体思路就是通过注解在策略类上指定约定好的type,项目启动之后将所有有注解的type获取到,根据type存储,然后在业务中根据type获取对应的策略即可

模拟订单业务,根据订单的type,需要不同的处理逻辑,比如,免费订单,半价订单等,下面是项目结构:

springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改..._第1张图片

 

一 策略接口和实现

/**
 * 处理订单策略
 */
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();
    }
    public Order add(String filed,Object value){
        switch (filed){
            case "name":
                this.setName(String.valueOf(value));
                break;
            case "price":
                this.setPrice((Double) value);
                break;
            case "type":
                this.setType((Integer) value);
                break;
        }
        return this;
    }

省略set,get,提供链式风格方法编程

四 核心功能实现

主要就是这一块实现策略逻辑

/**
 * 根据订单类型返回对应的处理策略
 */
@Component
public class HandlerOrderContext {
    @Autowired
    private ApplicationContext applicationContext;
    //存放所有策略类Bean的map
    public static Map> orderStrategyBeanMap= new HashMap<>();

    public OrderStrategy getOrderStrategy(Integer type){
        Class 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 orderStrategyMap = applicationContext.getBeansWithAnnotation(HandlerOrderType.class);
        orderStrategyMap.forEach((k,v)->{
            Class orderStrategyClass = (Class) 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,实现新增策略代码零修改..._第2张图片

再添加策略添加实现类,启用注解即可!

省去了工厂模式,直接用注解实现,避免修改工厂类,

这里贴一个我们之前项目的工厂类实现:

springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改..._第3张图片

如果再添加策略还是会有轻微的改动!

转载于:https://www.cnblogs.com/houzheng/p/10911462.html

你可能感兴趣的:(springboot中使用自定义注解实现策略模式,去除工厂模式的switch或ifelse,实现新增策略代码零修改...)