如何服务中使用状态机

举报
码乐 发表于 2024/12/19 10:41:34 2024/12/19
【摘要】 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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。