颜力刚Ligang Yan

如何设计购物车页面:一次系统设计模拟面试

购物车是电商网站的关键一环,用户在这里核对和调整选购内容再去结账。一次模拟面试的整理:功能需求、数据结构与 API 设计,以及为什么购物车的计算逻辑应该放在后端。

mock-interviewshopping-cartsystem-design

English version: How to Design a Shopping Cart Page: A System Design Mock Interview

购物车页面是任何电商网站的关键组成部分,用户在这里核对和修改自己选购的商品,然后再去付款。设计一个好用的购物车页面,功能需求和非功能需求都要仔细考虑。

功能需求

购物车页面必须有这几项功能:

  • 展示购物车:包括总价、折扣和最终价格。
  • 加入购物车:把商品加进购物车。
  • 从购物车移除:删掉不想要的商品。
  • 修改数量:调整每件商品的数量。
  • 勾选和取消勾选:选择哪些商品参与结账。
  • 结账:发起结账流程,跳转到支付页面。

数据结构与 API 设计

以下数据结构和接口可以实现上面的功能。

展示购物车

请求:

GET /api/cart

响应:

{
  "totalSelectItems": 2,
  "cartItems": [
    {
      "skuId": "123",
      "cover": "https://example.com/cover.jpg",
      "name": "Product A",
      "description": "Product A description",
      "quantity": 2,
      "price": 100,
      "discountPrice": 90,
      "finalPrice": 180,
      "isSelect": true
    },
    {
      "skuId": "124",
      "cover": "https://example.com/cover.jpg",
      "name": "Product B",
      "description": "Product B description",
      "quantity": 1,
      "price": 200,
      "discountPrice": 180,
      "finalPrice": 180,
      "isSelect": true
    }
  ],
  "promotions": [
    {
      "promotionId": "123",
      "type": "discount",
      "description": "Buy 2 get 1 free",
      "isSelect": true
    }
  ],
  "currency": "USD",
  "totalPrice": 360,
  "discountPrice": 330,
  "finalPrice": 330
}

加入购物车

请求:

POST /api/cart/add
{
  "skuId": "123",
  "quantity": 1
}

响应:

{
  "code": 200,
  "message": "Success"
}

从购物车移除

请求:

POST /api/cart/remove
{
  "skuId": "123"
}

修改数量

请求:

POST /api/cart/modify
{
  "skuId": "123",
  "quantity": 2
}

勾选和取消勾选

请求:

POST /api/cart/select
{
  "skuId": "123",
  "isSelect": true
}

结账

请求:

POST /api/cart/checkout

响应:

{
  "orderId": "123",
  "redirectUrl": "https://example.com/pay?orderId=123"
}

以上移除、修改、勾选三个接口的响应和“加入购物车”相同,返回状态码和消息即可。

非功能需求

信息正确性

为了保证数据一致,购物车的计算逻辑应该放在后端。好处有两点:

  1. 数据一致:把计算集中在后端,Android、iOS、Web 各端拿到的结果完全一样。对促销规则复杂的电商平台来说这一点很关键,避免各端团队各自实现造成的不一致。
  2. 前端更快更简单:计算下沉到后端,前端架构变简单,性能也更好。

但这个做法也有代价:

  1. 后端负载增加:计算集中意味着后端算力需求上升。
  2. 网络请求变多:每次改动数量或勾选都要请求一次后端,延迟增加可能影响前端体验。可以用本地乐观更新加后端最终校验来缓解。

English version.