小编在公司负责的就是订单取消业务,老系统中各类类型订单取消都是经过if else 判断不一样的订单类型进行不一样的逻辑。在经历老系统的折磨和产品需求的不断变动,小编决定进行一次大的重构:消灭 if else。java
接下来就向你们介绍下是如何消灭 if else。git
@Service
public class CancelOrderService {
public void process(OrderDTO orderDTO) {
int serviceType = orderDTO.getServiceType();
if (1 == serviceType) {
System.out.println("取消即时订单");
} else if (2 == serviceType) {
System.out.println("取消预定订单");
} else if (3 == serviceType) {
System.out.println("取消拼车订单");
}
}
}
复制代码
若干个月再来看就是这样的感受 github
@Service
public class CancelOrderStrategyService {
@Autowired
private StrategyContext context;
public void process(OrderDTO orderDTO) {
OrderTypeEnum orderTypeEnum = OrderTypeEnum.getByCode(orderDTO.getServiceType());
AbstractStrategy strategy = context.getStrategy(orderTypeEnum);
strategy.process(orderDTO);
}
}
复制代码
简洁的有点过度了是否是!!!spring
下面选取了即时订单和预定订单的策略.ide
@Service
@OrderTypeAnnotation(orderType = OrderTypeEnum.INSTANT)
public class InstantOrderStrategy extends AbstractStrategy {
@Override
public void process(OrderDTO orderDTO) {
System.out.println("取消即时订单");
}
}
复制代码
@Service
@OrderTypeAnnotation(orderType = OrderTypeEnum.BOOKING)
public class BookingOrderStrategy extends AbstractStrategy {
@Override
public void process(OrderDTO orderDTO) {
System.out.println("取消预定订单");
}
}
复制代码
public abstract class AbstractStrategy {
abstract public void process(OrderDTO orderDTO);
}
复制代码
每一个策略中增长了注解OrderTypeAnnotation,以标注适用于不一样类型的策略内容.post
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderTypeAnnotation {
OrderTypeEnum orderType();
}
复制代码
其中最为核心的为StrategyProcessor 策略处理器类和StrategyContext 策略上下文,this
@Component
public class StrategyProcessor implements BeanFactoryPostProcessor {
private static final String STRATEGY_PACKAGE = "com.lujiahao.strategy";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<OrderTypeEnum, Class> handlerMap = Maps.newHashMapWithExpectedSize(3);
ClassScanner.scan(STRATEGY_PACKAGE, OrderTypeAnnotation.class).forEach(clazz -> {
OrderTypeEnum type = clazz.getAnnotation(OrderTypeAnnotation.class).orderType();
handlerMap.put(type, clazz);
});
StrategyContext context = new StrategyContext(handlerMap);
configurableListableBeanFactory.registerSingleton(StrategyContext.class.getName(), context);
}
}
复制代码
public class StrategyContext {
private Map<OrderTypeEnum, Class> strategyMap;
public StrategyContext(Map<OrderTypeEnum, Class> strategyMap) {
this.strategyMap = strategyMap;
}
public AbstractStrategy getStrategy(OrderTypeEnum orderTypeEnum) {
if (orderTypeEnum == null) {
throw new IllegalArgumentException("not fond enum");
}
if (CollectionUtils.isEmpty(strategyMap)) {
throw new IllegalArgumentException("strategy map is empty,please check you strategy package path");
}
Class clazz = strategyMap.get(orderTypeEnum);
if (clazz == null) {
throw new IllegalArgumentException("not fond strategy for type:" + orderTypeEnum.getCode());
}
return (AbstractStrategy) SpringBeanUtils.getBean(clazz);
}
}
复制代码
咱们使用了枚举做为Map中的key,相信你们不多有人这样操做过,不过能够放心操做.经过下面两篇文章解答你们的疑问.spa
策略模式极大的减小if else等模板代码,在提高代码可读性的同时,也大大增长代码的灵活性,添加新的策略便可以知足业务需求. 本人在我司业务中对策略模式的应用获得了很好的验证,今后不再用担忧产品改需求. 用策略模式一时爽,一直用一直爽😏!.net
完整代码3d
欢迎你们关注😁