参考资料
需要开发一个购物车下单的功能,针对不同用户进行不同处理
⏹分析需求
⏹商品实体类
import lombok.Data;
import java.math.BigDecimal;
@Data
public class Item {
// 商品ID
private long id;
// 商品数量
private int quantity;
// 商品单价
private BigDecimal price;
// 商品优惠
private BigDecimal couponPrice;
// 商品运费
private BigDecimal deliveryPrice;
}
⏹购物车实体类
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Data
public class Cart {
// 商品清单
private List<Item> items = new ArrayList<>();
// 总优惠
private BigDecimal totalDiscount;
// 商品总价
private BigDecimal totalItemPrice;
// 总运费
private BigDecimal totalDeliveryPrice;
// 应付总价
private BigDecimal payPrice;
}
process
方法放在抽象类中。processCouponPrice
和processDeliveryPrice
则由继承抽象类的子类去实现,然后抽象类父类使用。import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public abstract class CartAbstract {
// 处理购物车的大量重复逻辑在父类实现
public Cart process(Map<Long, Integer> items) {
// 商品List
List<Item> itemList = new ArrayList<>();
items.forEach((itemId, itemCount) -> {
Item item = new Item();
// 设置商品的id
item.setId(itemId);
// 根据商品id,从数据库中获取商品的价格,※此处指定所有的商品价格都是10元
item.setPrice(new BigDecimal(10));
// 设置商品的数量
item.setQuantity(itemCount);
itemList.add(item);
});
// 让子类处理每一个商品的优惠
itemList.forEach(item -> {
// 处理商品优惠的逻辑
processCouponPrice(item);
// 处理配送费的逻辑
processDeliveryPrice(item);
});
// 将处理之后的商品逻辑添加到购物车中
Cart cart = new Cart();
cart.setItems(itemList);
// 计算商品总价
BigDecimal totalItemPrice = cart.getItems().stream()
.map(
item -> item
.getPrice()
.multiply(BigDecimal.valueOf(item.getQuantity()))
)
.reduce(BigDecimal.ZERO, BigDecimal::add);
cart.setTotalItemPrice(totalItemPrice);
// 计算总运费
BigDecimal totalDeliveryPrice = cart.getItems().stream()
.map(Item::getDeliveryPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
cart.setTotalDeliveryPrice(totalDeliveryPrice);
// 计算总折扣
BigDecimal totalDiscount = cart.getItems().stream()
.map(Item::getCouponPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
cart.setTotalDiscount(totalDiscount);
// 计算应付价格
BigDecimal payPrice = cart.getTotalItemPrice()
.add(cart.getTotalDeliveryPrice())
.subtract(cart.getTotalDiscount());
cart.setPayPrice(payPrice);
return cart;
}
// 处理商品优惠的逻辑留给子类实现
protected abstract void processCouponPrice(Item item);
// 处理配送费的逻辑留给子类实现
protected abstract void processDeliveryPrice(Item item);
}
if else
分支去处理很不好维护,因此将每一种类型的用户单独创建一个类,然后通过Spring来统一管理。applicationContext.getBean
来使用工厂模式来动态的生成购物车的处理对象,从而完成了解耦,提高了可维护性。import org.springframework.stereotype.Service;
import java.math.BigDecimal;
// 普通用户
@Service("NormalUserCart")
public class NormalUserCart extends CartAbstract {
// 计算优惠价格
@Override
protected void processCouponPrice(Item item) {
// 普通用户无优惠价格
item.setCouponPrice(BigDecimal.ZERO);
}
// 计算运费
@Override
protected void processDeliveryPrice(Item item) {
// 普通用户的运费为商品总价的10%
BigDecimal deliveryPrice = item
.getPrice()
.multiply(BigDecimal.valueOf(item.getQuantity()))
.multiply(new BigDecimal("0.1"));
item.setDeliveryPrice(deliveryPrice);
}
}
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
// VIP用户
@Service("VipUserCart")
public class VipUserCart extends CartAbstract implements InitializingBean {
private static BigDecimal discountPercent = BigDecimal.ONE;
@Override
public void afterPropertiesSet() {
// 模拟从数据库根据用户ID查询打折力度
discountPercent = new BigDecimal("80").divide(new BigDecimal("100"));
}
// 计算优惠价格
@Override
protected void processCouponPrice(Item item) {
// VIP用户购买两件以下的商品,不享受优惠价
if (item.getQuantity() <= 2) {
item.setCouponPrice(BigDecimal.ZERO);
return;
}
// VIP用户购买两件以以上的商品,优惠价(模拟优惠价为8折)
BigDecimal couponPrice = item.getPrice()
.multiply(discountPercent)
.multiply(BigDecimal.valueOf(item.getQuantity() - 2));
item.setCouponPrice(couponPrice);
}
// 计算运费
@Override
protected void processDeliveryPrice(Item item) {
// VIP用户的运费为商品总价的10%
BigDecimal deliveryPrice = item
.getPrice()
.multiply(BigDecimal.valueOf(item.getQuantity()))
.multiply(new BigDecimal("0.1"));
item.setDeliveryPrice(deliveryPrice);
}
}
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
// 内部用户
@Service("InternalUserCart")
public class InternalUserCart extends CartAbstract {
// 计算优惠价格
@Override
protected void processCouponPrice(Item item) {
// 内部用户无优惠价格
item.setCouponPrice(BigDecimal.ZERO);
}
// 计算运费
@Override
protected void processDeliveryPrice(Item item) {
// 内部用户无运费
item.setDeliveryPrice(BigDecimal.ZERO);
}
}
@RequiredArgsConstructor
配合@NonNull
来实现注入applicationContext.getBean(bean名称)
来使用工厂模式,动态的生成购物车处理对象import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@RequiredArgsConstructor
public class ZTestController implements CommandLineRunner {
// 通过lombok注入ApplicationContext
@NonNull
private ApplicationContext applicationContext;
@Override
public void run(String... args) throws Exception {
// 商品数量
Map<Long, Integer> cartItem = new HashMap<>(){
{
// key: 商品id, value: 商品数量
put(1L, 2);
put(2L, 10);
put(3L, 4);
}
};
Map<Integer, String> userCategoryMap = new HashMap<>(){
{
// key: 用户id, value: 用户身份标识
put(1, "Internal");
put(2, "Normal");
put(3, "Vip");
}
};
userCategoryMap.forEach((userId, userCategory) -> {
CartAbstract cartInfo = (CartAbstract) applicationContext.getBean(userCategory + "UserCart");
Cart cart = cartInfo.process(cartItem);
System.out.println("当前用户身份为: " + userCategory);
System.out.println("商品总优惠为: " + cart.getTotalDiscount());
System.out.println("商品总价格为: " + cart.getTotalItemPrice());
System.out.println("商品总运费为: " + cart.getTotalDeliveryPrice());
System.out.println("商品应付总价为: " + cart.getPayPrice());
System.out.println("----------------------------------------");
});
}
}