go: Flyweight Pattern

项目结构:

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]))
}

输出:

相关推荐
xyq20242 小时前
TypeScript中的String类型详解
开发语言
小糖学代码8 小时前
LLM系列:1.python入门:15.JSON 数据处理与操作
开发语言·python·json·aigc
handler018 小时前
从源码到二进制:深度拆解 Linux 下 C 程序的编译与链接全流程
linux·c语言·开发语言·c++·笔记·学习
小白学大数据9 小时前
现代Python爬虫开发范式:基于Asyncio的高可用架构实战
开发语言·爬虫·python·架构
渔舟小调9 小时前
P19 | 前端加密通信层 pikachuNetwork.js 完整实现
开发语言·前端·javascript
不爱吃炸鸡柳9 小时前
数据结构精讲:树 → 二叉树 → 堆 从入门到实战
开发语言·数据结构
网络安全许木9 小时前
自学渗透测试第21天(基础命令复盘与DVWA熟悉)
开发语言·网络安全·渗透测试·php
t***5449 小时前
如何在Dev-C++中使用Clang编译器
开发语言·c++
码界筑梦坊9 小时前
93-基于Python的中药药材数据可视化分析系统
开发语言·python·信息可视化