• 设计模式中的策略模式
  • 发布于 2个月前
  • 502 热度
    0 评论
首先简单讨论几个问题:
1.设计模式就是为了重用代码?基本是的,同时也方便扩展维护
2.策略模式就是一堆if...else...?是的
3.策略模式通常和什么模式搞基?最直观模版模式。
最初原型:
if("红包".equals(grantType)){
    //...
}else if ("会员".equals(grantType)){
    //...
}
这么写有问题吗?我个人觉得没有任何问题,但确实新增判断分支时需要改这块代码逻辑,不易维护扩展,而且每个条件分支没什么依赖,却被耦合在一起,使用switch...case...类似。

不建议使用map<type,Bean>:
我为什么不建议使用map将处理类型和处理bean收集起来?假设使用map进行收集,那么你需要初始化组装这个map,如下:
Map<String, Bean> map = new HashMap<String, Bean>(8){{
    put("红包",getBean());
    put("会员",getBean());
}};
按类型进行收集,然后用的时候再根据类型获取对应的bean。显然这里put操作需要维护,所以不建议使用这种方式。

不建议使用applicationContext去getBean:
还有具体的处理类的名字当作一种类型,通过这个beanName来获取bean,如下:
applicationContext.getBean("红包",ICouponService.class);
需要根据beanName来获取bean,beanName需要作为参数传进来,先不说beanName和业务类型名字大相径庭,传beanName就有点诡异。

个人愚见:
1.使用接口定义规范
public interface ICouponService {
    //堆代码 duidaima.com
    //优惠券是否支持
    boolean canDiscount(String couponStrArr);
    //计优惠后金额
    void discount(CouponContext couponContext);
    //获取优惠
    int getMinusAmount(long userid);
}
2.最常见的模式:模版模式
public abstract class AbstractCouponService implements ICouponService{
    @Override
    public void discount(CouponContext couponContext) {
        couponContext.finalAmount = couponContext.totalAmount - getMinusAmount(couponContext.getUid());
    }
}
 3.if判断应该在策略类里
// 堆代码 duidaima.com
@Service
public class RedPacketCouponServiceImpl extends AbstractCouponService{
    String grantType = "红包优惠";
    @Override
    public boolean canDiscount(String couponStrArr) {
        return couponStrArr.contains(grantType);
    }
    @Override
    public int getMinusAmount(long uid) {
        return 100;
    }
}
@Service
public class VipCouponServiceImpl extends AbstractCouponService {
    String grantType = "会员优惠";
    @Override
    public boolean canDiscount(String couponStrArr) {
        return couponStrArr.contains(grantType);
    }
    @Override
    public void discount(CouponContext couponContext) {
        couponContext.finalAmount = couponContext.finalAmount * getMinusAmount(couponContext.getUid()) / 100;
    }
    @Override
    public int getMinusAmount(long uid) {
        return 80;
    }
}
4.支持哪些策略应该动态配置,这里使用apollo
@RestController
@RequestMapping("/coupon")
public class CouponController {
    @Value("${coupon.strarr:}")
    String couponStrArr;
}    
5.使用List收集所有策略
@Autowired
private List<ICouponService> couponServiceList;
// 堆代码 duidaima.com
@GetMapping("cacl")
public ResultInfo caclCoupon(int totalAmount){
    CouponContext couponContext = CouponContext.builder().totalAmount(totalAmount).build();
    couponServiceList.stream().filter(e->e.canDiscount(couponStrArr)).forEach(e->e.discount(couponContext));
    return ResultInfo.success(couponContext);
}
本文从实际应用出发,抽象出简化版的优惠扣减模型,采用模版模式&策略模式完成。策略模式本质就是if...else...,开发应用也不该被设计模式所束缚,策略多了自然就会使用策略模式了。
用户评论