当前位置:   article > 正文

Java设计模式——策略模式与活动优惠_java 多种优惠混合使用 设计模式

java 多种优惠混合使用 设计模式

写在前面的话:项目基本完结了,复盘项目时,突发奇想,负责的模块居然符合策略模式的使用场景,所以引入策略模式,重构了下负责的模块,在此记录一下。

1. 业务场景

用户购票过程中,可以参加符合条件的优惠活动,并根据不同类型活动,计算优惠金额和支付金额,活动类型包括:

1. 立减活动
2. 立减到活动
3. 满减活动
  • 1
  • 2
  • 3

2. 传统处理/策略模式

2.1 传统模式
	if (KaActivityCinemaOrderEnum.NOW_REDUCTION.getCode().equals(activityType)) {
        // 立减活动计算逻辑
    } else if (KaActivityCinemaOrderEnum.NOW_REDUCTION_TO.getCode().equals(activityType)) {
        // 立减到活动计算逻辑
    } else {
        // 满减活动计算逻辑
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
2.2 策略模式
    CalculationDiscountContext context = new CalculationDiscountContext();
    Long discount = context.getActivityDiscountAmount(String.valueOf(activityType), activityCode, activityType, ticketOrderNo, seatCount);
  • 1
  • 2
2.3 什么是策略模式

https://blog.csdn.net/u012401711/article/details/524633479 (喜欢这类大神的讲解,形象便于理解,有兴趣的同学可以看看)

3. SpringBoot引入策略模式

在这里插入图片描述

  1. 创建抽象类或接口类

     @Component
     public abstract class CalculationDiscountAmount {
    
         @Autowired
         public KaActivityCinemaOrderDao kaActivityCinemaOrderDao;
     
         @Autowired
         public KaActivityFullSubtractDao kaActivityFullSubtractDao;
    
         public static CalculationDiscountAmount calculationDiscountAmount;
    
         /**
          * 在方法上加上注解@PostConstruct,保证Bean初始化前已经装配了属性(注:Bean初始化包括,实例化Bean,并装配Bean的属性(依赖注入))
          */
         @PostConstruct
         public void init() {
             calculationDiscountAmount = this;
         }
    
         public abstract Long getActivityDiscountAmount(Integer activityCode, Integer activityType, String ticketOrderNo, Integer count);
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  2. 创建实现类并重写抽象方法

    @Component
    public class FullReductionDiscountImpl extends CalculationDiscountAmount {
    
       private Logger logger = LoggerFactory.getLogger(TicketSupplementActivityServiceImpl.class);
    
       @Override
       public Long getActivityDiscountAmount(Integer activityCode, Integer activityType, String ticketOrderNo, Integer count) {
           try {
              	// 优惠计算逻辑
           } catch (Exception e) {
               logger.error("计算活动优惠金额异常,activityCode" + activityCode + ",activityType" + activityType + ",ticketOrderNo" + ",count" + count, e);
               throw new ArithmeticException();
           }
           return result;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  3. 创建计算优惠金额容器

     @Component
     public class CalculationDiscountContext {
     	@Autowired
     	private final Map<String, CalculationDiscountAmount> map = new ConcurrentHashMap<>();
    
         public CalculationDiscountContext() {
             this.map.clear();
             map.put(String.valueOf(KaActivityCinemaOrderEnum.FULL_REDUCTION.getCode()), new FullReductionDiscountImpl());
         }
     
         public Long getActivityDiscountAmount(String poolId, Integer activityCode, Integer activityType, String ticketOrderNo, Integer count) {
             return map.get(poolId).getActivityDiscountAmount(activityCode, activityType, ticketOrderNo, count);
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  4. 测试用例

     @Test
     public void CalculationDiscountContext() {
         String activityType = "3";
         CalculationDiscountContext context = new CalculationDiscountContext();
         context.getActivityDiscountAmount(activityType, 2210, Integer.valueOf(activityType), "81729381298379", 2);
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

4. 策略模式优势

	1. 耦合性大大降低,代码不再堆积;
	2. 在有多种算法相似的情况下,解决 if...else 所带来的复杂和难以维护问题;
	3. 具有良好的扩张性,如果活动增加时,只需要增加实现类和实现逻辑即可。
  • 1
  • 2
  • 3

5. 问题与解决方法

	1. 传统方式通过Spring管理对象
	解决方法:由于Spring管理对象时,由于一个抽象类有多个实现会报异常。所以使用了ConcurrentHashMap,根据不同类型,获取不同的实例对象,也可以使用注解的方式。
	2. @Component注解类中@Autowired注入对象为null
	解决方法:在方法上加上注解@PostConstruct,保证Bean初始化前已经装配了属性(注:Bean初始化包括,实例化Bean,并装配Bean的属性(依赖注入))
	(https://blog.csdn.net/z595746437/article/details/80340836)
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/92806
推荐阅读
相关标签
  

闽ICP备14008679号