## 背景
小李已经是一个工作一年的初级工程师了,他所在的公司是一家大型购物商场。随着各种网络购物软件兴起,老板也想做一个商场的购物 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());
}
主要用到了工厂模式、策略模式