Java设计模式之策略模式(注解方式)

文章目录

  • 1、常见场景
  • 2、示例代码
    • 2.1 订单类
    • 2.2 订单类型枚举类
    • 2.3 渠道枚举类
    • 2.4 订单支付后置处理适配器
    • 2.5 订单处理器注解
    • 2.6 订单支付后置处理器持有器
    • 2.7 持有器配置类
    • 2.7 订单服务类
    • 2.8 订单支付回调后置处理器类
    • 2.9 测试

1、常见场景

在支付成功回调方法中,往往需要对不同来源的订单做不同的处理;在积分兑换、抽奖等场景中,往往需要对不同类型的商品做不同的处理……此类场景最简单的实现方式是用if-else分支结构,然而随着业务不断增加,if-else分支结构会变得臃肿且难以维护,这时可以考虑使用策略模式实现。

2、示例代码

此处以订单支付成功后的回调处理为例,订单可以分为违章缴罚、六年免检、线上年审、驾驶证补换、行驶证补换等不同类型的订单,以及来源于微信公众号、微信小程序、电话营销、线上预约等不同的渠道。不同类型及不同渠道的订单都各自对应不同的后置处理逻辑。

2.1 订单类

@Data
public class Order {

    //订单编号
    private String orderId;

    //订单名称
    private String orderName;

    //订单类型
    private Integer orderType;

    //渠道标识
    private String channelTag;

    //实收金额
    private BigDecimal realAmount;
    
    //其他字段……
}

2.2 订单类型枚举类

public enum OrderType {

    WZJF(1,"违章缴罚"),
    LNMJ(2,"六年免检"),
    JSZBH(3,"驾驶证补换"),
    XSZBH(4,"行驶证补换"),
    XSNS(5,"线上年审"),
    JYYYY(6,"警医邮预约");

    private final Integer type;
    private final String desc;

    OrderType(Integer type, String desc) {
        this.type = type;
        this.desc = desc;
    }

    public Integer getType() {
        return type;
    }
}

2.3 渠道枚举类

public enum Channel {
    
    WXGZH("wxgzh","微信公众号"),
    JFXCX("jfxcx","缴罚小程序"),
    NSXCX("nsxcx","年审小程序"),
    DHYX("dhyx","电话营销");
    
    private final String tag;
    private final String desc;

    Channel(String tag, String desc) {
        this.tag = tag;
        this.desc = desc;
    }

    public String getTag() {
        return tag;
    }
}

2.4 订单支付后置处理适配器

定义一个统一的订单支付后置处理接口,后续不同类型、渠道的订单支付后置处理器皆实现此接口。

public interface OrderPayPostProcessAdapter {
    void orderPayPostProcess(Order order);
}

2.5 订单处理器注解

定义一个订单处理器注解,用于订单支付后置处理器上。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OrderProcessor {

    OrderType[] orderType();

    Channel[] channel();
}

2.6 订单支付后置处理器持有器

定义一个订单支付后置处理器持有器,用于存放订单支付后置处理器,并提供一个获取订单支付后置处理器的方法。

public class OrderPayPostProcessorHolder {

    private static final Map<String, OrderPayPostProcessAdapter> HOLDER = new HashMap<>();

    public OrderPayPostProcessorHolder(List<OrderPayPostProcessAdapter> list) {
        if (list != null && list.size() > 0){
            for (OrderPayPostProcessAdapter orderPayPostProcessAdapter : list) {
                OrderProcessor orderProcessor = AnnotationUtils.findAnnotation(orderPayPostProcessAdapter.getClass(), OrderProcessor.class);
                if (orderProcessor != null){
                    OrderType[] orderTypeArr = orderProcessor.orderType();
                    Channel[] channelArr = orderProcessor.channel();
                    for (int i = 0; i < orderTypeArr.length; i++) {
                        for (int j = 0; j < channelArr.length; j++) {
                            //以orderType_channel作为key,如:1_wxgzh
                            String key = orderTypeArr[i].getType() + "_" + channelArr[j].getTag();
                            HOLDER.put(key, orderPayPostProcessAdapter);
                        }
                    }
                }
            }
        }
    }

    public OrderPayPostProcessAdapter getOrderPayPostProcessor(Integer orderType, String channelTag){
        String key = orderType + "_" + channelTag;
        return HOLDER.get(key);
    }
}

2.7 持有器配置类

把订单支付后置处理器持有器交给Spring容器管理。

@Configuration
public class HolderConfig {

    @Bean
    public OrderPayPostProcessorHolder orderPayPostProcessorHolder(List<OrderPayPostProcessAdapter> list){
        return new OrderPayPostProcessorHolder(list);
    }

}

2.7 订单服务类

@Service
public class OrderService {

    @Autowired
    private OrderPayPostProcessorHolder orderPayPostProcessorHolder;

    /**
     * 订单支付回调处理
     * @param order
     */
    public void orderPayPostProcess(Order order){
        OrderPayPostProcessAdapter orderPayPostProcessor = orderPayPostProcessorHolder.getOrderPayPostProcessor(order.getOrderType(), order.getChannelTag());
        if (orderPayPostProcessor != null){
            orderPayPostProcessor.orderPayPostProcess(order);
        }
    }
}

2.8 订单支付回调后置处理器类

按照业务需要创建不同的订单支付回调后置处理器类

@Service
@OrderProcessor(orderType = {OrderType.WZJF, OrderType.LNMJ, OrderType.JSZBH, OrderType.XSZBH, OrderType.XSNS},
                channel = {Channel.WXGZH, Channel.JFXCX, Channel.NSXCX})
public class OrderPayPostProcessor01 implements OrderPayPostProcessAdapter {
    @Override
    public void orderPayPostProcess(Order order) {
        System.out.println("订单支付后置处理器1:处理普通订单……");
    }
}
@Service
@OrderProcessor(orderType = {OrderType.JYYYY},channel = {Channel.DHYX})
public class OrderPayPostProcessor02 implements OrderPayPostProcessAdapter {
    @Override
    public void orderPayPostProcess(Order order) {
        System.out.println("订单支付后置处理器2:处理电话营销渠道的警医邮预约订单……");
    }
}
@Service
@OrderProcessor(orderType = {OrderType.XSNS},channel = {Channel.DHYX})
public class OrderPayPostProcessor03 implements OrderPayPostProcessAdapter {
    @Override
    public void orderPayPostProcess(Order order) {
        System.out.println("订单支付后置处理器3:处理电话营销渠道的线上年审订单……");
    }
}

2.9 测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestStrategy {

    @Autowired
    private OrderService orderService;

    @Test
    public void test1() throws Exception{
        Order order = new Order();
        order.setOrderId("202101010001");
        order.setOrderName("缴罚小程序的违章缴罚订单(普通订单)");
        order.setOrderType(OrderType.WZJF.getType());
        order.setChannelTag(Channel.JFXCX.getTag());
        orderService.orderPayPostProcess(order);
        //print: 订单支付后置处理器1:处理普通订单……
    }

    @Test
    public void test2() throws Exception{
        Order order = new Order();
        order.setOrderId("202101010002");
        order.setOrderName("电话营销渠道的警医邮预约订单");
        order.setOrderType(OrderType.JYYYY.getType());
        order.setChannelTag(Channel.DHYX.getTag());
        orderService.orderPayPostProcess(order);
        //print:订单支付后置处理器2:处理电话营销渠道的警医邮预约订单……
    }

    @Test
    public void test3() throws Exception{
        Order order = new Order();
        order.setOrderId("202101010003");
        order.setOrderName("电话营销渠道的线上年审订单");
        order.setOrderType(OrderType.XSNS.getType());
        order.setChannelTag(Channel.DHYX.getTag());
        orderService.orderPayPostProcess(order);
        //print:订单支付后置处理器3:处理电话营销渠道的线上年审订单……
    }
}

你可能感兴趣的:(设计模式,java,设计模式)