今天我们来了解下设计模式中比较常用的策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,使每个算法可以相互替代,使算法本身和使用算法的客户端分割开来,相互独立。(摘自百度)
一个大功能,它有许多不同类型的实现(策略类),具体根据客户端来决定采用特定的策略类。
比如下单、物流对接、网关的加签验签等。
具体业务为每个物流公司都有它们对应的code,加签方法,物流查询方法
首先我们定义好接口类
public interface Logistics {
    /**
     * 物流公司唯一标识
     * @return
     */
    String companyCode();
    /**
     * 加签
     * @param request
     */
    String sign(SignRequest request);
    /**
     * 查询物流信息
     */
    LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request);
}
对接顺风和圆通
@service("shunfengLogistics")
public class ShunfengLogistics implements Logistics {
    @Override
    public String companyCode() {
        return "shunfeng";
    }
    @Override
    public String sign(SignRequest request) {
        //do your biz
        
        return null;
    }
    @Override
    public LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request) {
        //do your biz
        
        return null;
    }
}
@service("yuantongLogistics")
public class YuantongLogistics implements Logistics {
    @Override
    public String companyCode() {
        return "yuantong";
    }
    @Override
    public String sign(SignRequest request) {
        //do your biz
        
        return null;
    }
    @Override
    public LogisticsInfoResponse queryLogisticsInfo(QueryLogisticsInfoRequest request) {
        //do your biz
        
        return null;
    }
}
public class LogisticsFactory {
    @Autowired
    private Logistics shunfengLogistics;
    @Autowired
    private Logistics yuantongLogistics;
    public Logistics getLogistics(LogisticsRequest request) {
        String company = request.getCompanyCode();
        if ("shunfeng".equals(company)) {
        
            return shunfengLogistics;
        }
        if ("yuantong".equals(company)) {
       
            return yuantongLogistics;
        }
        
        throw new BizException("物流公司类型错误");
    }
}
每当我们接入一家物流公司的时候都要使LogisticsFactory加一段if分支。这就违反了设计模式的开闭原则
其实不结合Spring特性的话,策略模式还是有上述问题存在。
我们先来准备下spring相关知识
1.实现InitializingBean接口。相信这个大家并不陌生。就是spring容器创建bean的时候帮你执行初始化的接口
2.实现ApplicationContextAware接口。通俗的讲,实现了这个接口的bean相当于是拿到了ApplicationContext,相当于整个spring容器的资源。
3.ApplicationContext接口的getBeansOfType方法。获取整个spring容器中某个类型的bean,返回的是map类型。key对应beanName, value对应bean。
@Component
public class LogisticsResolver implements InitializingBean, ApplicationContextAware {
    private ApplicationContext applicationContext;
    private Map<String, Sign> logisticsHandlerMap = new HashMap<>();
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    @Override
    public void afterPropertiesSet() {
        Map<String, Sign> beanMap = applicationContext.getBeansOfType(Logistics.class);
        for (String key : beanMap.keySet()) {
            this.signHandlerMap.put(beanMap.get(key).companyCode(), beanMap.get(key));
        }
    }
    public Logistics getHandler(String companyCode) {
        return logisticsHandlerMap.get(companyCode);
    }
}
通过spring容器去获取对应的所有实现类,并组装成我们想要的companyCode→bean的map。通过getHandler方法就能拿到对应的实现类。
但是现在我们每次加一个策略类的时候都交由Spring去管理,只管加就行了
原文:https://www.cnblogs.com/chenshengyue/p/10826087.html