No2.大话设计模式学习之订单结算模块

## 背景

小李已经是一个工作一年的初级工程师了,他所在的公司是一家大型购物商场。随着各种网络购物软件兴起,老板也想做一个商场的购物 APP。分给小李的是一个一个订单结算模块,需要支持各种不同的结算策略。

## 需求

请帮小李写一个订单结算模块,要求支持多种结算策略:

- 原价
- 打 X 折
- 满减,满 X 元减 Y 元

请注意,商品有多种类型,每种类型可能会参与不同的活动,自然需要支持不同的结算策略。

## 任务

共三个小任务:

- Q1:方案设计。
- Q2:代码实现及结果截图。
- Q3:解释为什么要用这些模式。

## 要求

要求如下:

- 输入是一揽子商品,输出是最后的订单金额。
- 至少包含两种商品,每种使用不同的结算策略,策略可任选其中一个或两个组合(比如满减 + 打折)。
- 不要实现具体函数或方法的逻辑,可以使用 `print` 输出功能。

// 收费抽象类
public abstract class CashSuper{
    public abstract double acceptCash(double money);
}

// 正常收费类
public class CashNormal extends CashSuper {

    @Override
    public double acceptCash(double money) {
        return money;
    }
}

// 打折类
@Data
public class CashRebate extends CashSuper {
    /**
     * 折扣数
     */
    private double moneyRebate;

    public CashRebate(String moneyRebate) {
        this.moneyRebate = Double.parseDouble(moneyRebate);
    }

    @Override
    public double acceptCash(double money) {
        return money * moneyRebate;
    }

}

// 满减类
@Data
public class CashReturn extends CashSuper {
    /**
     * 满减起始金额
     */
    private double moneyCondition;
    /**
     * 满减金额
     */
    private double moneyReturn;

    public CashReturn(String moneyCondition, String moneyReturn) {
        double condition = Double.parseDouble(moneyCondition);
        double returnTemp = Double.parseDouble(moneyReturn);
        this.moneyCondition = condition;
        // 最多满减 300-30 这种
        this.moneyReturn = returnTemp > condition * 0.1 ? condition * 0.1 : returnTemp;
    }

    @Override
    public double acceptCash(double money) {
        if(money >= this.moneyCondition) {
            return money - Math.floor(money / this.moneyCondition) * moneyReturn;
        }
        return money;
    }
}

// 折满减
public class RebateAndReturn extends CashSuper {
    /**
     * 折扣数
     */
    private double moneyRebate;

    /**
     * 满减起始金额
     */
    private double moneyCondition;
    /**
     * 满减金额
     */
    private double moneyReturn;

    public RebateAndReturn(String moneyRebate, String moneyCondition, String moneyReturn) {
        double condition = Double.parseDouble(moneyCondition);
        double returnTemp = Double.parseDouble(moneyReturn);
        this.moneyRebate = Double.parseDouble(moneyRebate);
        this.moneyCondition = condition;
        // 最多满减 300-30 这种
        this.moneyReturn = returnTemp > condition * 0.1 ? condition * 0.1 : returnTemp;
    }

    @Override
    public double acceptCash(double money) {
        double rebateMoney = money * moneyRebate;
        if (rebateMoney >= this.moneyCondition) {
            return rebateMoney - Math.floor(rebateMoney / this.moneyCondition) * moneyReturn;
        }
        return rebateMoney;
    }
}

// 上下文
public class CashContext {

    private CashSuper cs;
    private Double money = 0D ;
    private List<Product> products = new ArrayList<>() ;

    public CashSuper getCs(String type) {
        switch (type) {
            case "正常收费":
                this.cs = new CashNormal();
                break;
            case "满返":
                this.cs = new CashReturn("300", "100");
                break;
            case "打折":
                this.cs = new CashRebate("0.8");
                break;
            case "折完减":
                this.cs = new RebateAndReturn("0.8", "300", "100");
                break;
        }
        return cs;
    }

    public CashContext() {

    }

    public CashContext(List<Product> products) {
        this.products = products;
    }

    /**
     * 计算商品总金额
     * @return
     */
    public double getResult() {
        LinkedHashMap<String, List<Product>> productMap = CollectionUtils.emptyIfNull(products).stream().collect(Collectors.groupingBy(Product::getProductType, LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<Product>> entry : productMap.entrySet()) {
            String productType = entry.getKey();
            List<Product> productList = entry.getValue();
            double sum = CollectionUtils.emptyIfNull(productList).stream().collect(Collectors.summingDouble(product -> product.getNum() * product.price));
            money += getCs(productType).acceptCash(sum);
        }
        return money;
    }

    public void addProduct(Product product) {
        if (null != product) {
            products.add(product);
        }
    }
}

// 基础商品
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
    /**
     * 商品类型
     */
    public String productType;
    /**
     * 商品名称
     */
    public String name;

    /**
     * 商品价格
     */
    public double price;
    /**
     * 商品数量
     */
    public Integer num;
    /**
     * 商品id
     */
    public Long id;
}

// 正常商品
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class NormalProduct extends Product {
    /**
     * 商品类型
     */
    public String productType = "正常收费";
}
// 打折后减商品
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RebateAndReturnProduct extends Product {
    /**
     * 商品类型
     */
    public String productType = "折完减";
}

// 打折商品
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RebateProduct extends Product {
    /**
     * 商品类型
     */
    public String productType = "打8折";
}
// 满减商品
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReturnProduct extends Product {
    /**
     * 商品类型
     */
    public String productType = "满300返100";
}

// 商品工厂
public interface ProductFactory {
    public Product createProduct(String name, Double price, int num, Long id);
}

// 普通商品工厂
public class NormalProductFactory implements ProductFactory{

    @Override
    public NormalProduct createProduct(String name, Double price, int num, Long id) {
        NormalProduct normalProduct = new NormalProduct();
        normalProduct.setProductType("正常收费");
        normalProduct.setName(name);
        normalProduct.setId(id);
        normalProduct.setPrice(price);
        normalProduct.setNum(num);
        return normalProduct;
    }
}

// 打折商品工厂
public class RebateProductFactory implements ProductFactory{

    @Override
    public RebateProduct createProduct(String name, Double price, int num, Long id) {
        RebateProduct rebateProduct = new RebateProduct();
        rebateProduct.setProductType("打8折");
        rebateProduct.setName(name);
        rebateProduct.setId(id);
        rebateProduct.setPrice(price);
        rebateProduct.setNum(num);
        return rebateProduct;
    }
}

// 满减商品工厂
public class ReturnProductFactory implements ProductFactory{

    @Override
    public ReturnProduct createProduct(String name, Double price, int num, Long id) {
        ReturnProduct returnProduct = new ReturnProduct();
        returnProduct.setProductType("满300返100");
        returnProduct.setName(name);
        returnProduct.setId(id);
        returnProduct.setPrice(price);
        returnProduct.setNum(num);
        return returnProduct;
    }
}

// 打折后减商品工厂
public class RebateAndReturnProductFactory implements ProductFactory{

    @Override
    public RebateAndReturnProduct createProduct(String name, Double price, int num, Long id) {
        RebateAndReturnProduct rebateAndReturnProduct = new RebateAndReturnProduct();
        rebateAndReturnProduct.setProductType("折完减");
        rebateAndReturnProduct.setName(name);
        rebateAndReturnProduct.setId(id);
        rebateAndReturnProduct.setPrice(price);
        rebateAndReturnProduct.setNum(num);
        return rebateAndReturnProduct;
    }
}

// 主类

public static void main(String[] args) {
        CashContext cashContext = new CashContext();
        cashContext.addProduct(new NormalProductFactory().createProduct("包治百病",100D,10,1L));
        cashContext.addProduct(new NormalProductFactory().createProduct("玫瑰花",200D,10,2L));
        // 打折商品
        cashContext.addProduct(new RebateProductFactory().createProduct("八音盒",300D,10,3L));
        cashContext.addProduct(new RebateProductFactory().createProduct("围巾",400D,10,4L));
        // 折后减
        cashContext.addProduct(new RebateAndReturnProductFactory().createProduct("西瓜",500D,10,5L));
        cashContext.addProduct(new RebateAndReturnProductFactory().createProduct("火锅",600D,10,6L));
        // 满减
        cashContext.addProduct(new ReturnProductFactory().createProduct("烤肉",700D,10,7L));
        cashContext.addProduct(new ReturnProductFactory().createProduct("排骨",800D,10,8L));
        System.out.println(cashContext.getResult());
    }

 主要用到了工厂模式、策略模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值