设计模式 ---- 策略模式最佳实践(二)

156 阅读2分钟

本來策略模式只写了上边一篇文章的,文章发出来以后经过大佬指导,代码可以更加简化,趁着今天有时间就按大佬的提示修改了一版,请各位品鉴(案例还是用上文的案例)。

废话少说,直接上代码

首先定义接口,接口中就只有一个方法了,即获取商品的促销价格。

package com.info.examples.strategy;

import java.math.BigDecimal;

public interface PromoteSalesService {

    /**
     * 获取商品促销价
     *
     * @param originalPrice 原价
     * @return 商品的促销价
     */
    BigDecimal getPromotionPrice(BigDecimal originalPrice);
}


实现接口

package com.info.examples.strategy;

import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 打折促销
 */
@Service
public class DiscountPromoteServiceImpl implements PromoteSalesService {

    // 满100打9折,199以上打85折
    @Override
    public BigDecimal getPromotionPrice(BigDecimal originalPrice) {
        if (new BigDecimal("100").compareTo(originalPrice) > 0) {
            return originalPrice;
        } else if (new BigDecimal("199").compareTo(originalPrice) >= 0) {
            return originalPrice.multiply(new BigDecimal("0.9"));
        }
        return originalPrice.multiply(new BigDecimal("0.85"));
    }
}

package com.info.examples.strategy;

import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 满减促销
 */
@Service
public class FullReductionPromoteServiceImpl implements PromoteSalesService {

    // 满 199 减 50
    @Override
    public BigDecimal getPromotionPrice(BigDecimal originalPrice) {
        if (new BigDecimal("199").compareTo(originalPrice) > 0) {
            return originalPrice;
        }
        return originalPrice.subtract(new BigDecimal("50"));
    }
}

定义一个促销方式的枚举

package com.info.examples.strategy;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 支持的促销方式枚举
 */
@AllArgsConstructor
@Getter
public enum PromoteTypeEnum {

    // 打折
    DISCOUNT("打折", new DiscountPromoteServiceImpl()),

    // 满减
    FULL_REDUCTION("满减", new FullReductionPromoteServiceImpl());

    private String desc;

    private PromoteSalesService service;

}

至此主体代码编写完毕,不再需要所谓的策略模式的上下文,可以开始测试。

package com.info.examples.controller;

import com.info.examples.strategy.PromoteSalesService;
import com.info.examples.strategy.PromoteStrategyFactory;
import com.info.examples.strategy.PromoteTypeEnum;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Random;

@RestController
public class PromoteController {

    @GetMapping("/getPrice/{price:^[1-9]\\d*$|^(?>[1-9]\\d*\\.\\d{1,8})$}")
    public String getPromotePrice(@PathVariable String price) {
        PromoteTypeEnum promoteType = new Random().nextInt(100) > 50 ? PromoteTypeEnum.FULL_REDUCTION : PromoteTypeEnum.DISCOUNT;
        PromoteTypeEnum promoteType = new Random().nextInt(100) > 50 ? PromoteTypeEnum.FULL_REDUCTION : PromoteTypeEnum.DISCOUNT;
        BigDecimal promotionPrice = promoteType.getService().getPromotionPrice(new BigDecimal(price));
        return String.format("原价 %s 使用 %s 促销后价格为 %f", price, promoteType.getDesc(), promotionPrice.doubleValue());
    }
}

启动项目,打开浏览器输入http://localhost:8080/getPrice/200就可以进行测试啦。

可以看到,效果和之前是一样的,其实到这儿你会发现,具体的实现类我们也可以不需要,可以把具体的实现内容写到枚举里面,因此枚举类变成了这个样子:

package com.info.examples.strategy;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.math.BigDecimal;

/**
 * 支持的促销方式枚举
 */

@Getter
@AllArgsConstructor
public enum PromoteTypeEnum {

    // 打折
    DISCOUNT("打折", originalPrice -> {
        if (new BigDecimal("100").compareTo(originalPrice) > 0) {
            return originalPrice;
        } else if (new BigDecimal("199").compareTo(originalPrice) >= 0) {
            return originalPrice.multiply(new BigDecimal("0.9"));
        }
        return originalPrice.multiply(new BigDecimal("0.85"));
    }),

    // 满减
    FULL_REDUCTION("满减", originalPrice -> {
        if (new BigDecimal("199").compareTo(originalPrice) > 0) {
            return originalPrice;
        }
        return originalPrice.subtract(new BigDecimal("50"));
    });

    private String desc;

    private PromoteSalesService service;
}

好了今天的分享就到这里,打完收工!

在这里插入图片描述