设计模式之策略模式在业务中的使用

一,什么是策略模式

策略模式(Strategy Pattern)是一种常用的设计模式,属于行为型模式。它允许在运行时选择算法或操作的策略,通过定义一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。

简单来说,策略模式是多态的一种体现,我个人认为不同与多态的点在于策略模式比多态多了一个“中转站”上下文这么一个东西。通过这个上下文,我们才能够灵活的实现具体业务中需要的哪一个策略,就调用哪个策略,摆脱多if的烦恼,所以它是一个很重要的角色。

主要组成部分

策略模式主要包含三个角色:

  1. Context(上下文):用来维护对当前选定策略对象的引用。
  2. Strategy(策略接口):定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法。
  3. 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;
    }
}

三,测试结果

四,总结

其实设计模式并不是什么高大上的东西,它是一种软件开发过程中,约定俗成的规则和方法。多使用设计模式到开发中,能够提升自己的开发思维,也能使代码更优雅和规范,也希望大家能够把设计模式代打开发中去,谢谢看到这里。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值