首先简单讨论几个问题:
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...,开发应用也不该被设计模式所束缚,策略多了自然就会使用策略模式了。