优惠券系统 (较完整实现+策略模式)

概要

实现一个优惠券系统,实现了优惠券的扣减功能、优惠券间叠加校验、优惠券的门槛校验,同时使用策略模式对不同类型的优惠券实现金额的扣减。

代码

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 优惠券系统
 */
public class Coupon {
    // 券之间的叠加规则(每种优惠券只能使用一次)
    String rule = "{\"1\":[{\"id\":1,\"value\":1}], \"2\":[{\"id\":2,\"value\":1}]}";

    public static void main(String[] args) {
        // 定义两张优惠券
        CouponEntity couponEntity1 = new CouponEntity(1, "满300减30券", 1, "{\"amount\":300}", 30);
        CouponEntity couponEntity2 = new CouponEntity(2, "7折优惠券(满300)", 2, "{\"amount\":300}", 70);
        List<CouponEntity> couponEntities = new ArrayList<>();
        couponEntities.add(couponEntity1);
        couponEntities.add(couponEntity2);

        // 定义商品
        Good good1 = new Good("三得利", "淘宝", 50);
        Good good2 = new Good("鼠标", "淘宝", 250);
        Good good3 = new Good("键盘", "天猫", 300);
        List<Good> goodList = new ArrayList<>();
        goodList.add(good1);
        goodList.add(good2);
        goodList.add(good3);

        double price = count(couponEntities, goodList);
    }

    // 计算订单总价
    public static double count(List<CouponEntity> couponEntities, List<Good> goodList) {
        // 判断券组合是否合法
        if (!valid(couponEntities)) {
            throw new RuntimeException("券组合非法");
        }

        // 为了方便直接计算所有商品总和
        double total = goodList.stream().mapToDouble(Good::getPrice).sum();

        for (CouponEntity couponEntity : couponEntities) {
            // 判断是否达到使用门槛

            total = couponEntity.getPrice(total);
        }

        return total;
    }

    public static boolean valid(List<CouponEntity> couponEntities) {
        Map<Integer, Long> collect = couponEntities.stream()
                .collect(Collectors.groupingBy(CouponEntity::getId, Collectors.counting()));

        for (int id : collect.keySet()) {
            /**
             * 伪代码
             * 券之间的叠加规则(每种优惠券只能使用一次)
             * String rule = "{\"1\":[{\"id\":1,\"value\":1}], \"2\":[{\"id\":2,\"value\":1}]}";
             * ruleJson = JSON.parse(rule);
             * array = ruleJson.getJSONArray(id);
             * if (array == null) continue;
             * for (JSON json : array) {
             *     if (collect.getOrDefault(json.get("id"), 0) > json.get("value")) {
             *         return false;
             *     }
             * }
             */
        }
        return true;
    }
}

/**
 * 优惠券对象
 */
class CouponEntity{
    private int id;
    private String name;
    // 1比例扣减、2定额扣减
    private int type;

    // 门槛json {"shop":"1", "amount":100, "grade":2}
    private String condition;

    // 扣减的金额/比例
    private double amount;

    private Count countService;

    public int getType() {
        return type;
    }

    public CouponEntity(int id, String name, int type, String condition, double amount) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.condition = condition;
        this.amount = amount;
        if (type == 1) {
            this.countService = new Discount1();
        } else {
            this.countService = new Discount2();
        }
    }

    public double getPrice(double price) {
        return countService.count(price, amount);
    }
}

interface Count{
    double count(double price, double amount);
}

//比例扣减
class Discount1 implements Count{

    @Override
    public double count(double price, double amount) {
        return price * amount / 100;
    }
}

//定额扣减
class Discount2 implements Count{

    @Override
    public double count(double price, double amount) {
        return price - amount;
    }
}

class Good{
    private String name;
    private String shop;
    private double price;

    public double getPrice() {
        return price;
    }

    public Good(String name, String shop, double price) {
        this.name = name;
        this.shop = shop;
        this.price = price;
    }
}

小结

涉及到不同类型进行不同的操作,可以采用策略模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值