项目结构:

Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 21:00
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : jewelry_category.go
*/
package flyweight
import (
"fmt"
"godesginpattern/flyweight/errors"
)
// JewelryCategoryFlyweight 享元接口(共享内部状态)
type JewelryCategoryFlyweight interface {
CategoryID() string
CategoryName() string
Material() string
Style() string
BasePrice() float64
BaseInfo() string
}
// jewelryCategory 实现
type jewelryCategory struct {
categoryID string
categoryName string
material string
style string
basePrice float64
}
func (j *jewelryCategory) CategoryID() string { return j.categoryID }
func (j *jewelryCategory) CategoryName() string { return j.categoryName }
func (j *jewelryCategory) Material() string { return j.material }
func (j *jewelryCategory) Style() string { return j.style }
func (j *jewelryCategory) BasePrice() float64 { return j.basePrice }
func (j *jewelryCategory) BaseInfo() string {
return fmt.Sprintf("品类ID:%s | 名称:%s | 材质:%s | 款式:%s | 基础价:%.2f",
j.categoryID, j.categoryName, j.material, j.style, j.basePrice)
}
// NewJewelryCategory 创建享元
func NewJewelryCategory(id, name, material, style string, basePrice float64) (JewelryCategoryFlyweight, error) {
if id == "" {
return nil, errors.ErrCategoryEmpty
}
return &jewelryCategory{
categoryID: id,
categoryName: name,
material: material,
style: style,
basePrice: basePrice,
}, nil
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 21:00
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : inventory.go
*/
package inventory
import (
"fmt"
"godesginpattern/flyweight/domain/flyweight"
)
type JewelryStatus string
const (
StatusOnSale JewelryStatus = "在售"
StatusSoldOut JewelryStatus = "已售罄"
StatusOffline JewelryStatus = "已下架"
)
// JewelryInventory 库存实体(外部状态)
type JewelryInventory struct {
UniqueCode string
StockNum int
OnlineTime string
SalePrice float64
Status JewelryStatus
Category flyweight.JewelryCategoryFlyweight
}
func (j *JewelryInventory) FullInfo() string {
return fmt.Sprintf(
"[%s] %s | 唯一码:%s | 库存:%d | 售价:%.2f | 状态:%s",
j.Category.CategoryID(), j.Category.BaseInfo(),
j.UniqueCode, j.StockNum, j.SalePrice, j.Status,
)
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 20:59
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : category_factory.go
*/
package factory
import (
"context"
"godesginpattern/flyweight/domain/flyweight"
"log"
"sync"
)
// FlyweightFactory 享元工厂接口
type FlyweightFactory interface {
GetCategory(ctx context.Context, req NewCategoryReq) (flyweight.JewelryCategoryFlyweight, error)
Count() int
}
type NewCategoryReq struct {
CategoryID string
CategoryName string
Material string
Style string
BasePrice float64
}
// categoryFactory 实现
type categoryFactory struct {
mu sync.RWMutex
cache map[string]flyweight.JewelryCategoryFlyweight
}
func NewCategoryFactory() FlyweightFactory {
return &categoryFactory{
cache: make(map[string]flyweight.JewelryCategoryFlyweight),
}
}
func (f *categoryFactory) GetCategory(ctx context.Context, req NewCategoryReq) (flyweight.JewelryCategoryFlyweight, error) {
f.mu.RLock()
cate, ok := f.cache[req.CategoryID]
f.mu.RUnlock()
if ok {
log.Printf("[工厂] 复用品类:%s", req.CategoryID)
return cate, nil
}
f.mu.Lock()
defer f.mu.Unlock()
if cate, ok = f.cache[req.CategoryID]; ok {
return cate, nil
}
newCate, err := flyweight.NewJewelryCategory(
req.CategoryID, req.CategoryName, req.Material, req.Style, req.BasePrice,
)
if err != nil {
return nil, err
}
f.cache[req.CategoryID] = newCate
log.Printf("[工厂] 创建新品类:%s", req.CategoryID)
return newCate, nil
}
func (f *categoryFactory) Count() int {
f.mu.RLock()
defer f.mu.RUnlock()
return len(f.cache)
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 20:59
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : inventory_service.go
*/
package service
import (
"context"
"godesginpattern/flyweight/domain/flyweight"
"godesginpattern/flyweight/domain/inventory"
"godesginpattern/flyweight/errors"
"log"
)
// InventoryService 库存服务接口
type InventoryService interface {
CreateInventory(ctx context.Context, req CreateInventoryReq) *inventory.JewelryInventory
Query(ctx context.Context, inv *inventory.JewelryInventory) string
SaleOut(ctx context.Context, inv *inventory.JewelryInventory, num int) error
}
type CreateInventoryReq struct {
UniqueCode string
OnlineTime string
SalePrice float64
Category flyweight.JewelryCategoryFlyweight
}
// inventoryService 实现
type inventoryService struct{}
func NewInventoryService() InventoryService {
return &inventoryService{}
}
func (s *inventoryService) CreateInventory(ctx context.Context, req CreateInventoryReq) *inventory.JewelryInventory {
return &inventory.JewelryInventory{
UniqueCode: req.UniqueCode,
StockNum: 1,
OnlineTime: req.OnlineTime,
SalePrice: req.SalePrice,
Status: inventory.StatusOnSale,
Category: req.Category,
}
}
func (s *inventoryService) Query(ctx context.Context, inv *inventory.JewelryInventory) string {
return inv.FullInfo()
}
func (s *inventoryService) SaleOut(ctx context.Context, inv *inventory.JewelryInventory, num int) error {
if inv.StockNum < num {
return errors.ErrStockNotEnough
}
inv.StockNum -= num
if inv.StockNum == 0 {
inv.Status = inventory.StatusSoldOut
}
log.Printf("[销售] 出库成功:%s 剩余:%d", inv.UniqueCode, inv.StockNum)
return nil
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 20:59
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : jewelry_api.go
*/
package api
import (
"context"
"fmt"
"godesginpattern/flyweight/config"
"godesginpattern/flyweight/domain/inventory"
"godesginpattern/flyweight/infrastructure/factory"
"godesginpattern/flyweight/service"
)
// JewelryAPI 对外接口层
type JewelryAPI struct {
config *config.AppConfig
factory factory.FlyweightFactory
service service.InventoryService
}
func NewJewelryAPI(
cfg *config.AppConfig,
f factory.FlyweightFactory,
s service.InventoryService,
) *JewelryAPI {
return &JewelryAPI{
config: cfg,
factory: f,
service: s,
}
}
// BatchCreate 批量创建库存
func (api *JewelryAPI) BatchCreate(ctx context.Context, req factory.NewCategoryReq, count int) ([]*inventory.JewelryInventory, error) {
cate, err := api.factory.GetCategory(ctx, req)
if err != nil {
return nil, err
}
var list []*inventory.JewelryInventory
for i := 1; i <= count; i++ {
inv := api.service.CreateInventory(ctx, service.CreateInventoryReq{
UniqueCode: fmt.Sprintf("JM%06d", i),
OnlineTime: "2025-01-10",
SalePrice: cate.BasePrice() - 300,
Category: cate,
})
list = append(list, inv)
}
return list, nil
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 21:00
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : config.go
*/
package config
type AppConfig struct {
AppName string
Version string
}
func NewDefaultConfig() *AppConfig {
return &AppConfig{
AppName: "jewelry-inventory-system",
Version: "v1.0.0",
}
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 20:59
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : errors.go
*/
package errors
import "errors"
var (
ErrStockNotEnough = errors.New("库存不足")
ErrCategoryEmpty = errors.New("品类ID不能为空")
)
调用:
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Flyweight Pattern享元模式
# Author : geovindu,Geovin Du 涂聚文.
# IDE : goLang 2024.3.6 go 26.2
# os : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 Oracle 21c Neo4j
# Datetime : 2026/4/20 21:03
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : flyweightbll.go
flyweight/
├── go.mod # Go 模块
├── cmd/
│ └── main.go # 项目启动入口
├── config/
│ └── config.go # 应用配置
├── domain/
│ ├── flyweight/
│ │ └── jewelry_category.go # 享元(共享内部状态)
│ └── inventory/
│ └── inventory.go # 库存实体(外部状态)
├── infrastructure/
│ └── factory/
│ └── category_factory.go # 享元工厂(缓存/复用)
├── service/
│ └── inventory_service.go # 业务逻辑层
├── api/
│ └── jewelry_api.go # 对外接口/流程编排
└── common/
└── errors/
└── errors.go # 全局统一错误
*/
package bll
import (
"context"
"godesginpattern/flyweight/api"
"godesginpattern/flyweight/config"
"godesginpattern/flyweight/infrastructure/factory"
"godesginpattern/flyweight/service"
"log"
)
func FlyweightMain() {
ctx := context.Background()
cfg := config.NewDefaultConfig()
// 依赖注入
f := factory.NewCategoryFactory()
s := service.NewInventoryService()
api := api.NewJewelryAPI(cfg, f, s)
log.Println("=== 珠宝库存销售系统启动 ===")
// 创建10000件钻戒
diamond, _ := api.BatchCreate(ctx, factory.NewCategoryReq{
CategoryID: "C001",
CategoryName: "钻戒",
Material: "18K金",
Style: "经典六爪",
BasePrice: 5999,
}, 10000)
// 创建5000件黄金项链
gold, _ := api.BatchCreate(ctx, factory.NewCategoryReq{
CategoryID: "C002",
CategoryName: "黄金项链",
Material: "足金999",
Style: "简约锁骨链",
BasePrice: 2999,
}, 5000)
log.Printf("总库存:%d", len(diamond)+len(gold))
log.Printf("共享享元对象:%d", f.Count())
// 查询 & 销售
log.Println("\n=== 库存查询 ===")
log.Println(s.Query(ctx, diamond[0]))
log.Println("\n=== 销售出库 ===")
_ = s.SaleOut(ctx, diamond[0], 1)
log.Println(s.Query(ctx, diamond[0]))
}
输出:
