一,什么是策略模式
策略模式(Strategy Pattern)是一种常用的设计模式,属于行为型模式。它允许在运行时选择算法或操作的策略,通过定义一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。
简单来说,策略模式是多态的一种体现,我个人认为不同与多态的点在于策略模式比多态多了一个“中转站”上下文这么一个东西。通过这个上下文,我们才能够灵活的实现具体业务中需要的哪一个策略,就调用哪个策略,摆脱多if的烦恼,所以它是一个很重要的角色。
主要组成部分
策略模式主要包含三个角色:
- Context(上下文):用来维护对当前选定策略对象的引用。
- Strategy(策略接口):定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法。
- ConcreteStrategy(具体策略):实现Strategy接口的类,提供具体的算法实现。
二,具体案例
先看一代码结构,这里的我单独拿出一个包,避免与其它业务类混在一起。
不多说,直接上代码。这里我需要通过产品ID和产品类型去查询卖家ID,因为产品类型的不同,那位我就需要根据传递的类型去做判断,再去查询卖家ID,一般情况,就是用if或者swtich做判断。比如这样:
/**
* 获取商家Id
* @param productType 产品类型
* @param productId 产品ID
* @return
*/
private Long getMerchantId(int productType, Long productId) {
switch (productType){
case 0:
Mountings mountings = mountingsMapper.selectById(productId);
if (ObjectUtil.isEmpty(mountings)){
throw new ServiceException("车辆已不存在");
}
return mountings.getCreationUserId();
case 1:
Vehicles selectVehicle = vehiclesMapper.selectById(productId);
if (ObjectUtil.isEmpty(selectVehicle)){
throw new ServiceException("车辆已不存在");
}
return selectVehicle.getCreationUserId();
default:
throw new ServiceException("未知订单类型");
}
}
使用策略模式的话,就可以这样去做。第一步定义策略接口
public interface SellerUserIdStrategy {
/**
* 获取商家名称
* @param id 订单ID
* @return
*/
Long getSellerUserId(String id);
Integer getType();//订单类型 0-车辆 1-配件 2-托运 3-充值 4-会员升级
}
第二步,策略的具体实现,就实现这个接口,我这里有多个实现,就贴出两个经典的实现。每个实现最好使用@servce注解,使其被spring管理
@Service
public class MountingsOrderStrategy implements SellerUserIdStrategy {
@Resource
private MountingsOrderMapper mountingsOrderMapper;
@Resource
private MountingsMapper mountingsMapper;
@Override
public Long getSellerUserId(String id) {
MountingsOrder mountingsOrder = mountingsOrderMapper.selectById(Long.valueOf(id));
if(ObjectUtil.isNotEmpty(mountingsOrder)&&ObjectUtil.isNotEmpty(mountingsOrder.getMountingsId())){
Mountings mountings = mountingsMapper.selectById(mountingsOrder.getMountingsId());
return mountings.getCreationUserId();
}
return null;
}
@Override
public Integer getType() {
return 1;
}
}
@Service
public class ShippingOrderStrategy implements SellerUserIdStrategy {
@Resource
private ShippingOrderMapper shippingOrderMapper;
@Override
public Long getSellerUserId(String id) {
ShippingOrder shippingOrder = shippingOrderMapper.selectById(Long.valueOf(id));
return ObjectUtil.isNotEmpty(shippingOrder)?shippingOrder.getCreationUserId():null;
}
@Override
public Integer getType() {
return 2;
}
}
第三步,上线文的写法实现,使用@component注解,注册道spring
@Component
public class SellerUserIdStrategyContext {
private final Map<Integer, SellerUserIdStrategy> strategies;
@Autowired
public SellerUserIdStrategyContext(List<SellerUserIdStrategy> strategyList) {
//在项目启动时,把具体的策略实现设置到这个map中。
this.strategies = new HashMap<>();
strategyList.forEach(strategy -> this.strategies.put(strategy.getType(), strategy));
}
//会员升级和充值的卖家为平台,暂返回0
public Long getSellerUserId(String id, Integer type) {
//这里传入产品ID和产品类型,就可以根据这个类型去调用具体的哪一个策略实现
SellerUserIdStrategy strategy = strategies.get(type);
if (strategy != null) {
return strategy.getSellerUserId(id);
}
return null;
}
}
三,测试结果
四,总结
其实设计模式并不是什么高大上的东西,它是一种软件开发过程中,约定俗成的规则和方法。多使用设计模式到开发中,能够提升自己的开发思维,也能使代码更优雅和规范,也希望大家能够把设计模式代打开发中去,谢谢看到这里。