栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【策略模式】SpringBoot 使用自定义注解实现策略模式【订单场景模拟】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【策略模式】SpringBoot 使用自定义注解实现策略模式【订单场景模拟】

 一、前言

整体思路:通过在策略类上使用自定义注解,定义的orderType不同来区分各种订单,再根据不同的orderType将策略类存储,使用时再根据orderType获取策略类做不同的处理。

代码结构:(案例以京东、淘宝、苏宁订单类型为例)

 二、代码 1、自定义策略注解 注解
import com.hong.strategy.enums.OrderTypeEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OrderTypeAnnotation {
    
    OrderTypeEnum orderType();
}
 枚举
public enum OrderTypeEnum {
    TB(1, "淘宝订单"),
    JD(2, "京东订单"),
    SN(3, "苏宁订单");

    private Integer orderType;
    private String desc;

    OrderTypeEnum(int orderType, String desc) {
        this.orderType = orderType;
        this.desc = desc;
    }

    public static OrderTypeEnum getEnum(Integer orderType) {
        OrderTypeEnum[] typeArray = OrderTypeEnum.values();
        for (OrderTypeEnum typeEnum : typeArray) {
            if (typeEnum.getOrderType().equals(orderType)) {
                return typeEnum;
            }
        }
        return null;
    }

    //此处忽略get和set方法
}
2、策略接口和实现 说明
OrderStrategy-接口
        getUserInfo(获取用户信息)
        getGoodsInfo(获取商品信息)
        getDiscount(获取优惠金额)

AbstractOrderStrategy-抽象类
        实现OrderStrategy接口所有方法

JdOrderStrategy-京东订单策略类
        继承AbstractOrderStrategy抽象类
        重写getGoodsInfo、getDiscount

SnOrderStrategy-苏宁订单策略类
        继承AbstractOrderStrategy抽象类
        重写getGoodsInfo、getDiscount

TbOrderStrategy-淘宝订单策略类
        继承AbstractOrderStrategy抽象类
        重写getGoodsInfo

AbstractOrderStrategy抽象类做通用处理类,其他策略类用来做特殊处理类

例如:获取用户信息是通用的,那么我们不需要在策略类中去实现他;

每个平台的优惠不一样,我们则需要对每个平台做不同的处理,那么,这个就可以在策略类中重写getDiscount方法来实现。

 订单策略-接口
public interface OrderStrategy {

    
    String getUserInfo(String buyer);

    
    String getGoodsInfo(String goodsName);

    
    Double getDiscount();
}
 订单策略-抽象类

 存放一些通用的基础方法。若不同的实现类有不同的需求,可在实现类中重写该方法,来实现自定义业务逻辑

import com.hong.strategy.strategys.service.OrderStrategy;


public abstract class AbstractOrderStrategy implements OrderStrategy {

    
    @Override
    public String getUserInfo(String buyer) {
        return buyer;
    }

    
    @Override
    public String getGoodsInfo(String goodsName) {
        return goodsName;
    }

    
    @Override
    public Double getDiscount() {
        return 0.0;
    }
}
 京东订单-策略类
import com.hong.strategy.enums.OrderTypeEnum;
import com.hong.strategy.strategys.annotation.OrderTypeAnnotation;
import org.springframework.stereotype.Component;


@Component
@OrderTypeAnnotation(orderType = OrderTypeEnum.JD)
public class JdOrderStrategy extends AbstractOrderStrategy {

    
    @Override
    public String getGoodsInfo(String goodsName) {
        return "【京东】" + goodsName;
    }

    
    @Override
    public Double getDiscount() {
        return 50.0;
    }
}
 苏宁订单-策略类
import com.hong.strategy.enums.OrderTypeEnum;
import com.hong.strategy.strategys.annotation.OrderTypeAnnotation;
import org.springframework.stereotype.Component;


@Component
@OrderTypeAnnotation(orderType = OrderTypeEnum.SN) //使用注解标明策略类型
public class SnOrderStrategy extends AbstractOrderStrategy {

    
    @Override
    public String getGoodsInfo(String goodsName) {
        return "【苏宁】" + goodsName;
    }

    
    @Override
    public Double getDiscount() {
        return 100.0;
    }
}
 淘宝订单-策略类
import com.hong.strategy.enums.OrderTypeEnum;
import com.hong.strategy.strategys.annotation.OrderTypeAnnotation;
import org.springframework.stereotype.Component;


@Component
@OrderTypeAnnotation(orderType = OrderTypeEnum.TB)
public class TbOrderStrategy extends AbstractOrderStrategy {

    
    @Override
    public String getGoodsInfo(String goodsName) {
        return "【淘宝】" + goodsName;
    }
}
 3、核心功能实现
import com.hong.strategy.enums.BizResultCode;
import com.hong.strategy.enums.OrderTypeEnum;
import com.hong.strategy.exception.BizException;
import com.hong.strategy.strategys.annotation.OrderTypeAnnotation;
import com.hong.strategy.strategys.service.OrderStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;


@Component
public class HandlerOrderContext implements ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(HandlerOrderContext.class);

    
    private static final Object lock = new Object();

    
    private static Map> orderStrategyBeanMap = new HashMap<>();

    @Autowired
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        HandlerOrderContext.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }


    
    public static OrderStrategy getInstance(Integer orderType) {
        if (null == orderType) {
            throw new BizException(BizResultCode.ERR_PARAM.getCode(), "订单类型不能为空");
        }

        OrderTypeEnum orderTypeEnum = OrderTypeEnum.getEnum(orderType);
        if (null == orderTypeEnum) {
            throw new BizException(BizResultCode.ERR_PARAM.getCode(), "暂时不支持该订单类型orderType=" + orderType);
        }

        // 当集合为空时,则初始化
        if (orderStrategyBeanMap.size() == 0) {
            initStrategy();
        }

        Class clazz = orderStrategyBeanMap.get(orderTypeEnum);
        if (null == clazz) {
            throw new BizException(BizResultCode.ERR_PARAM.getCode(), "未找到订单类型(" + orderTypeEnum + ")的创建订单策略实现类");
        }
        // 从spring容器中获取bean
        return applicationContext.getBean(clazz);
    }

    
    private static void initStrategy() {
        synchronized (lock) {
            // 获取接口下所有实例bean
            Map strategyMap = applicationContext.getBeansOfType(OrderStrategy.class);
            if (null == strategyMap || strategyMap.size() == 0) {
                throw new BizException(BizResultCode.ERR_SYSTEM.getCode(), "代码配置错误:未获取到OrderStrategy的实现类,请检查代码中是否有将实现类bean注册到spring容器");
            }

            // 加载所有策略类对应的配置
            OrderTypeAnnotation annotation;
            for (Map.Entry strategy : strategyMap.entrySet()) {
                Class strategyClazz = strategy.getValue().getClass();
                // 因为策略bean可能是经过动态代理生成的bean实例(可能是多重动态代理后的代理对象),
                // 故而bean实例的class可能已经不是原来的class了,所以beanClass.getAnnotation(...)获取不到对应的注解元信息
                annotation = (OrderTypeAnnotation) strategyClazz.getAnnotation(OrderTypeAnnotation.class);
                if (null == annotation) {
                    // 当从bean实例的class上获取不到注解元信息时,通过AnnotationUtils工具类递归来获取
                    annotation = AnnotationUtils.findAnnotation(strategyClazz, OrderTypeAnnotation.class);
                    if (null == annotation) {
                        logger.warn("代码配置错误:创建订单策略实现类{}未配置OrderTypeAnnotation注解", strategyClazz.getName());
                        continue;
                    }
                }
                // 支持多个事件类型
                OrderTypeEnum typeEnum = annotation.orderType();
                //String key = getKey(typeEnum.getOrderType());
                if (orderStrategyBeanMap.containsKey(typeEnum)) {
                    logger.error("代码配置错误:一个订单类型({})只能对应一个创建订单策略实现{}", typeEnum, strategyClazz.getName());
                    throw new BizException(BizResultCode.ERR_SYSTEM.getCode(), "代码配置错误:一个订单类型(" + typeEnum + ")只能对应一个创建订单策略实现bean");
                }
                orderStrategyBeanMap.put(typeEnum, strategyClazz);
            }

            if (orderStrategyBeanMap.size() == 0) {
                logger.warn("初始化创建订单策略集合失败");
            }
        }
    }
}
 4、实体类
public class Order {
    
    private String buyer;
    
    private String goodsName;
    
    private Double price;
    
    private Integer orderType;

    //此处忽略get和set
}
5、业务层  接口
import com.hong.strategy.entity.Order;


public interface OrderService {
    String handleOrder(Order order);
}
 实现类
import com.hong.strategy.entity.Order;
import com.hong.strategy.service.OrderService;
import com.hong.strategy.strategys.config.HandlerOrderContext;
import com.hong.strategy.strategys.service.OrderStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Component
public class OrderServiceImpl implements OrderService {
    private static final Logger logger = LoggerFactory.getLogger(HandlerOrderContext.class);

    @Override
    public String handleOrder(Order order) {
        try {
            // 根据订单类型获取对应的创建订单策略
            OrderStrategy orderStrategy = HandlerOrderContext.getInstance(order.getOrderType());
            String userInfo = orderStrategy.getUserInfo(order.getBuyer());
            String goodsInfo = orderStrategy.getGoodsInfo(order.getGoodsName());
            Double discount = orderStrategy.getDiscount();

            String msg = "n购买人信息:" + userInfo +
                    "n商品信息:" + goodsInfo +
                    "n优惠金额:" + discount +
                    "n原价:" + order.getPrice() +
                    "n优惠后金额:" + (order.getPrice() - discount);

            logger.info(msg);
            return msg;
        } catch (Exception e) {
            return e.getMessage();
        }
    }
}
6、控制层
import com.hong.strategy.entity.Order;
import com.hong.strategy.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/handler")
    public String handleOrder(Integer orderType) {
        Order order = new Order();
        order.setBuyer("小明");
        order.setGoodsName("华为手机");
        order.setPrice(3999.9);
        order.setOrderType(orderType);
        return orderService.handleOrder(order);
    }
}
三、测试

 

四、源码地址(码云gitee):

annotation-strategy: SpringBoot 使用自定义注解实现策略模式【订单场景模拟】

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/305715.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号