Java OOP:如何向ArrayList添加商品、实现临期折扣及收银小票打印
Java超市购物系统功能实现方案
1. Food实例添加到Cart集合实现
首先修复原有Cart类的问题:
- 移除products属性不必要的static修饰(除非需要全局唯一购物车)
- 初始化products为ArrayList实例
- 优化add方法支持单个/批量添加商品,补充移除商品方法
- 因为Food继承自BaseProduct,基于多态特性可以直接存入
List<BaseProduct>集合
修改后的Cart类代码:
package Cart; import Products.BaseProduct; import Products.PerishableProducts.Food; import java.util.ArrayList; import java.util.Date; import java.util.List; public class Cart { // 初始化商品集合 private List<BaseProduct> products = new ArrayList<>(); // 添加单个商品 public void add(BaseProduct product) { // 前置校验:过期商品不能加入购物车 if (product instanceof Food) { Food food = (Food) product; if (new Date().after(food.getExpirationDate())) { throw new RuntimeException("商品已过期,无法加入购物车"); } } products.add(product); } // 批量添加商品 public void addBatch(List<BaseProduct> productList) { productList.forEach(this::add); } // 移除单个商品 public boolean remove(BaseProduct product) { return products.remove(product); } // 获取所有商品 public List<BaseProduct> getProducts() { return new ArrayList<>(products); } // 清空购物车 public void clear() { products.clear(); } }
2. 临期折扣逻辑实现
核心逻辑:计算购买日期和商品过期日期的间隔天数,间隔<5天则享受9折优惠,折扣金额为原价的10%。
推荐实现方案:
- 给抽象类BaseProduct新增抽象计算实付价格、折扣金额的方法,适配后续多品类折扣扩展
- Food类实现该方法,加入临期折扣判断逻辑
- 日期计算转成LocalDate处理,避免Date类的时区、时间戳计算误差问题
首先在BaseProduct抽象类新增抽象方法:
public abstract Double getActualPrice(Date buyDate); public abstract Double getDiscountAmount(Date buyDate);
Food类实现对应方法:
import java.time.LocalDate; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Date; // 实现抽象方法:获取实付价格 @Override public Double getActualPrice(Date buyDate) { return getPrice() * (1 - getDiscountRate(buyDate)); } // 实现抽象方法:获取折扣金额 @Override public Double getDiscountAmount(Date buyDate) { return getPrice() * getDiscountRate(buyDate); } // 私有方法计算折扣率 private double getDiscountRate(Date buyDate) { // 转成LocalDate计算天数差 LocalDate buyLocalDate = buyDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate expireLocalDate = expirationDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); // 计算间隔天数 long daysBetween = ChronoUnit.DAYS.between(buyLocalDate, expireLocalDate); // 不足5天返回0.1的折扣率(即减10%),否则无折扣 return daysBetween < 5 && daysBetween >= 0 ? 0.1 : 0d; }
3. Cashier收银员类实现
小票打印逻辑步骤:
- 接收Cart实例和购买日期参数
- 对购物车商品按名称+品牌分组统计购买数量
- 遍历分组计算每个商品的小计金额、折扣金额
- 累加得到总消费金额、总折扣金额
- 格式化打印小票内容
Cashier类代码:
package Service; import Cart.Cart; import Products.BaseProduct; import java.util.Date; import java.util.Map; import java.util.stream.Collectors; public class Cashier { public void printReceipt(Cart cart, Date buyDate) { // 按商品名称+品牌分组统计数量 Map<String, Long> countMap = cart.getProducts().stream() .collect(Collectors.groupingBy(p -> p.getName() + "-" + p.getBrand(), Collectors.counting())); // 按分组去重后的商品映射 Map<String, BaseProduct> productMap = cart.getProducts().stream() .collect(Collectors.toMap(p -> p.getName() + "-" + p.getBrand(), p -> p, (p1, p2) -> p1)); double totalAmount = 0d; double totalDiscount = 0d; // 打印小票头 System.out.println("====================购物小票===================="); System.out.printf("购买时间:%tF %tT%n", buyDate, buyDate); System.out.println("商品名称\t品牌\t单价\t数量\t小计\t折扣"); System.out.println("-----------------------------------------------"); // 遍历打印每个商品 for (String key : countMap.keySet()) { BaseProduct product = productMap.get(key); long count = countMap.get(key); double subTotal = product.getActualPrice(buyDate) * count; double subDiscount = product.getDiscountAmount(buyDate) * count; System.out.printf("%s\t%s\t%.2f\t%d\t%.2f\t%.2f%n", product.getName(), product.getBrand(), product.getPrice(), count, subTotal, subDiscount); totalAmount += subTotal; totalDiscount += subDiscount; } // 打印合计 System.out.println("-----------------------------------------------"); System.out.printf("总消费金额:%.2f 元%n", totalAmount); System.out.printf("总折扣金额:%.2f 元%n", totalDiscount); System.out.println("==============================================="); } }
注意事项
- 金额计算推荐用
BigDecimal替代Double,避免浮点数精度丢失问题 - 日期处理建议全量升级为Java8+的
LocalDate/LocalDateTime,废弃旧的Date类 - 可根据业务需求新增过期商品拦截、折扣叠加等扩展逻辑
内容的提问来源于stack exchange,提问作者georgik1_
相关产品推荐
相关产品推荐

