如何服务中使用状态机
【摘要】 1 简介一个商品买卖管理和订单的状态管理服务,本文试图说明他们是如何配合使用的和生效的。以下是一个使用 Go 编写的 Web 服务示例,它结合了 面向对象(OO)方法中的“封装” 和 信息工程中的“数据完整性约束” 实现商品买卖管理和订单状态管理功能。我们将展示如何通过封装保证服务接口的易用性和可靠性,以及如何通过数据完整性约束保证业务逻辑的正确性。 2. 场景描述封装:将商品库存管理、订...
1 简介
一个商品买卖管理和订单的状态管理服务,本文试图说明他们是如何配合使用的和生效的。
以下是一个使用 Go 编写的 Web 服务示例,它结合了 面向对象(OO)方法中的“封装” 和 信息工程中的“数据完整性约束” 实现商品买卖管理和订单状态管理功能。
我们将展示如何通过封装保证服务接口的易用性和可靠性,以及如何通过数据完整性约束保证业务逻辑的正确性。
2. 场景描述
封装:
将商品库存管理、订单创建和状态更新等功能封装为独立的业务逻辑模块,隐藏实现细节,暴露安全的接口。
通过封装避免外部直接修改商品库存或订单状态,从而保证数据一致性。
数据完整性约束:
商品库存不能为负数。
订单的状态必须遵循合法的流转规则:
Created → Paid → Shipped → Completed
或 Created → Cancelled。
3. 数据模型设计
实体设计:
Product:表示商品,包括库存信息。
Order:表示订单,包括状态和购买的商品数量。
约束设计:
Product 的库存减少时,必须保证库存非负。
Order 的状态流转必须符合约定规则。
4. Go 实现代码
package main
import (
"encoding/json"
"fmt"
"net/http"
"sync"
)
// Product 表示商品实体
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Stock int `json:"stock"` // 库存
Price float64 `json:"price"`
}
// Order 表示订单实体
type Order struct {
ID int `json:"id"`
ProductID int `json:"product_id"`
Quantity int `json:"quantity"`
Status string `json:"status"` // Created, Paid, Shipped, Completed, Cancelled
}
// 模拟数据库
var (
products = struct {
sync.Mutex
data map[int]*Product
}{data: make(map[int]*Product)}
orders = struct {
sync.Mutex
data map[int]*Order
}{data: make(map[int]*Order)}
)
// 创建商品
func createProductHandler(w http.ResponseWriter, r *http.Request) {
var product Product
if err := json.NewDecoder(r.Body).Decode(&product); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
products.Lock()
defer products.Unlock()
product.ID = len(products.data) + 1
products.data[product.ID] = &product
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(product)
}
// 创建订单
func createOrderHandler(w http.ResponseWriter, r *http.Request) {
var order Order
if err := json.NewDecoder(r.Body).Decode(&order); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
products.Lock()
defer products.Unlock()
orders.Lock()
defer orders.Unlock()
// 检查商品是否存在
product, exists := products.data[order.ProductID]
if !exists {
http.Error(w, "Product not found", http.StatusNotFound)
return
}
// 检查库存是否足够
if product.Stock < order.Quantity {
http.Error(w, "Not enough stock", http.StatusConflict)
return
}
// 减少库存并创建订单
product.Stock -= order.Quantity
order.ID = len(orders.data) + 1
order.Status = "Created"
orders.data[order.ID] = &order
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(order)
}
// 更新订单状态
func updateOrderStatusHandler(w http.ResponseWriter, r *http.Request) {
var input struct {
OrderID int `json:"order_id"`
Action string `json:"action"` // Pay, Ship, Complete, Cancel
}
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
orders.Lock()
defer orders.Unlock()
products.Lock()
defer products.Unlock()
// 检查订单是否存在
order, exists := orders.data[input.OrderID]
if !exists {
http.Error(w, "Order not found", http.StatusNotFound)
return
}
// 根据动作更新订单状态
switch input.Action {
case "Pay":
if order.Status != "Created" {
http.Error(w, "Order cannot be paid", http.StatusConflict)
return
}
order.Status = "Paid"
case "Ship":
if order.Status != "Paid" {
http.Error(w, "Order cannot be shipped", http.StatusConflict)
return
}
order.Status = "Shipped"
case "Complete":
if order.Status != "Shipped" {
http.Error(w, "Order cannot be completed", http.StatusConflict)
return
}
order.Status = "Completed"
case "Cancel":
if order.Status != "Created" {
http.Error(w, "Only created orders can be cancelled", http.StatusConflict)
return
}
order.Status = "Cancelled"
// 取消订单时恢复库存
product, productExists := products.data[order.ProductID]
if productExists {
product.Stock += order.Quantity
}
default:
http.Error(w, "Invalid action", http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(order)
}
// 查询商品列表
func listProductsHandler(w http.ResponseWriter, r *http.Request) {
products.Lock()
defer products.Unlock()
var productList []Product
for _, product := range products.data {
productList = append(productList, *product)
}
json.NewEncoder(w).Encode(productList)
}
// 查询订单列表
func listOrdersHandler(w http.ResponseWriter, r *http.Request) {
orders.Lock()
defer orders.Unlock()
var orderList []Order
for _, order := range orders.data {
orderList = append(orderList, *order)
}
json.NewEncoder(w).Encode(orderList)
}
func main() {
// 路由配置
http.HandleFunc("/products", createProductHandler) // 创建商品
http.HandleFunc("/orders", createOrderHandler) // 创建订单
http.HandleFunc("/orders/update", updateOrderStatusHandler) // 更新订单状态
http.HandleFunc("/products/list", listProductsHandler) // 查询商品列表
http.HandleFunc("/orders/list", listOrdersHandler) // 查询订单列表
// 启动服务器
fmt.Println("Server is running at http://localhost:8080")
http.ListenAndServe(":8080", nil)
}
5 示例说明
模块化实现:
createProductHandler 封装了商品创建逻辑,外部无法直接修改库存。
updateOrderStatusHandler 封装了订单状态更新逻辑,只允许合法的状态流转。
隐藏细节:
内部通过锁机制保护共享数据,外部调用者无需关心。
数据完整性约束
库存约束:
在 createOrderHandler 中,库存必须足够才能创建订单。
在订单取消时(Cancel),库存恢复,确保一致性。
状态约束:
订单状态必须按照规定顺序流转,避免非法状态。
6 测试
创建商品
curl -X POST -H "Content-Type: application/json" -d '{"name": "Laptop", "stock": 10, "price": 1200.50}' http://localhost:8080/products
创建订单
curl -X POST -H "Content-Type: application/json" -d '{"product_id": 1, "quantity": 2}' http://localhost:8080/orders
更新订单状态,支付订单:
curl -X POST -H "Content-Type: application/json" -d '{"order_id": 1, "action": "Pay"}' http://localhost:8080/orders/update
发货订单:
curl -X POST -H "Content-Type: application/json" -d '{"order_id": 1, "action": "Ship"}' http://localhost:8080/orders/update
完成订单:
curl -X POST -H "Content-Type: application/json" -d '{"order_id": 1, "action": "Complete"}' http://localhost:8080/orders/update
7. 总结
封装:模块化逻辑,隐藏数据操作细节,保证接口简洁和安全。
数据完整性约束:通过库存约束和状态流转规则,确保系统数据的一致性和正确性。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)