策略模式之注解形式

策略模式前言咱们在这里不重复了,大家可以看我上一篇文章 策略模式之简单形式,接下来我们一起对上一篇文章的弊端进行修复,这篇文章我们将通过注解的形式,简化调用逻辑,使接入方更方便使用,闲话少说,直接上代码

我们创建一个注解接口类  StockHandleType 其中 WmsOperateStockTypeEnum 是每种入库类型的枚举

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface StockHandleType {
    WmsOperateStockTypeEnum source();
}

再创建一个注解接口的实现类   StockHandleTypeImpl

public class StockHandleTypeImpl implements StockHandleType {
    private final WmsOperateStockTypeEnum source;

    StockHandleTypeImpl(WmsOperateStockTypeEnum source) {
        this.source = source;
    }

    @Override
    public WmsOperateStockTypeEnum source() {
        return source;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return StockHandleType.class;
    }

    @Override
    public int hashCode() {
        int hashCode = 0;
        hashCode += (127 * "source".hashCode()) ^ source.hashCode();
        return hashCode;
    }


    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof StockHandleType)) {
            return false;
        }
        StockHandleType other = (StockHandleType) obj;
        return source.equals(other.source());
    }
}

一定要记得要重写他的equals、hashCode方法

接口类StockHandle

public interface StockHandle {
    void operatorStock(WmsOperateStockParam stockParam);
    default void cancelStock(WmsOperateStockParam stockParam){}
}

实现类就是各个入库类型,我们只写一种类型数据最源头的入库上架 ,注意这个实现类与上篇文章的唯一不同点是加一个注解 StockHandleType 并且指明该实现是那个入库类型

@Component
@StockHandleType(source = WmsOperateStockTypeEnum.INBOUND_HELVES)
public class WmsInboundStockHandle implements StockHandle {
    @Resource
    private WmsStockOperateService wmsStockOperateService;
 
    @Override
    public void operatorStock(WmsOperateStockParam stockParam) {
        wmsStockOperateService.operateInboundStock(stockParam);
    }
}

我们再创建一个策略分发类 StockDistributeService 与上一篇Contex上下文类的作用类似

@Service
public class StockDistributeService {
    private static Map<StockHandleType, StockHandle> stockHandleMap;

    @Autowired
    public void setStockHandleMap(List<StockHandle> stockHandleList) {
        log.info("------------stockHandleMap----------开始,入参{}", JSONObject.toJSONString(stockHandleList));
        stockHandleMap = stockHandleList.stream().collect(Collectors.toMap(k -> Objects.requireNonNull(AnnotationUtils.findAnnotation(k.getClass(), StockHandleType.class)), v -> v, (k1, k2) -> k1));
    }

    public void operatorStock(WmsOperateStockParam param) {
      getStockHandle(param).operatorStock(param);
    }

    private StockHandle getStockHandle(WmsOperateStockParam param) {
        StockHandleTypeImpl stockHandleType = new StockHandleTypeImpl(WmsOperateStockTypeEnum.valueOf(param.getOperateStockType()));
        StockHandle stockHandle = stockHandleMap.get(stockHandleType);
        Assert.notNull(stockHandle, ErrorCode.PARAM_ERROR.value(), "操作库存类型系统中不存在 " + param.getOperateStockType() + " 实现类");
        return stockHandle;
    }
}

注解形式的策略模式基本写完了,下面我们来进行最后一步如何引用

public class Client {
    @Resource
    private StockDistributeService stockDistributeService;
 
    @Test
    public static void test(){
       WmsOperateStockParam param = new WmsOperateStockParam();
       //对param数据进行封装,省略
       stockDistributeService.operatorStock(param);
    }
}

总结:对该写法有以下几点思考

1、对于调用方,简化调用逻辑,只需要像平时调用普通的service接口一样简单,引用service + 调用对应的方法,不必关心该入口是哪个入库类型的处理类,同时也无需像上篇文章,指明处理类

2、采用注解的方式,提高代码的扩展性,当需要增加一种入库类型,我们只需要增加该入库逻辑的实现类,同时在该类上指明注解

3、如果不是增加入库类型,而是增加一个取消入库对方法,我们需要在StockDistributeService类里增加调用入口cancel方法,同时在StockHandle接口上增加 default void cancelStock(WmsOperateStockParam stockParam){} 加上default关键后,只需要在需要的实现类里重写该方法,而不会强制所有的实现类实现,提高了代码的延展性

4、如果每个入库类型的业务处理逻辑类似,例如第一步进行参数验证 第二步插入货位库存 第三步插入批次记录 第三步插入库存异动记录 第四步插入记录日志等,那么我们增加一种设计模式,我想大家都能猜出来,是模版模式,对上述的实现类WmsInboundStockHandle 进行改造。增加一个抽象类AbstractStockHandle,让该抽象类实现StockHandle接口,在该实现类中增加模版方法1、2、3 ,在入库方法 operatorStock中一次调用,通用逻辑在抽象类模版方法中调用,对于特殊的逻辑在各自的实现类中处理,具体代码这里就不详细列了。

预言:

下一篇文章我们用另外一种方式来避免判断选择入库类型。提前透露下,采用工厂方式,在工厂方式里维护一个Map,key是类型,value是每个实现类的对象

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值