首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >python: Flyweight Pattern

python: Flyweight Pattern

作者头像
geovindu
发布2026-06-18 19:18:51
发布2026-06-18 19:18:51
1200
举报

基于珠宝品类、库存、销售等核心实体来实现享元模式,重点区分「可共享的珠宝基础属性」和「个性化的销售 / 库存属性」,并通过实际业务流程(如库存查询、销售出库)展示模式价值。

代码语言:javascript
复制
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:享元模式 Flyweight Pattern
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/3/5 22:38
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : FlyweightPattern.py
from dataclasses import dataclass
 
 
# -------------------------- 1. 享元核心类(珠宝基础信息,共享内部状态) --------------------------
@dataclass(frozen=True)  # 冻结,确保内部状态不可变(享元对象必须不可变)
class JewelryBaseInfo:
    """
    珠宝基础信息(享元对象)- 仅包含可共享的内部状态
    """
    category: str
    """
    类:戒指/项链/手链/耳钉
    """
    material: str
    """
    材质:足金999/铂金PT950/18K金/钻石
    """
    style: str             #
    """
    款式:传承系列/小蛮腰/莫桑钻镶嵌/经典素圈
    """
    craft: str = "基础抛光"
    """
    基础工艺(默认值)
    """
 
    def get_base_desc(self) -> str:
        """
        返回基础信息描述(共享部分)
        :return:
        """
        return f"{self.material} {self.style} {self.category}(工艺:{self.craft})"
代码语言:javascript
复制
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:享元模式 Flyweight Pattern
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/3/5 22:43
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : JewelryFlyweightFactory.py
 
from typing import Dict, List
from FlyweightPattern.JewelryBaseInfo import JewelryBaseInfo
 
# -------------------------- 2. 享元工厂(管理珠宝基础信息,避免重复创建) --------------------------
class JewelryFlyweightFactory:
    """
    珠宝基础信息工厂 - 核心是缓存和复用享元对象
    """
    _flyweight_pool: Dict[tuple, JewelryBaseInfo] = {}  # 缓存池,键为内部状态组合
 
    @classmethod
    def get_jewelry_base_info(cls, category: str, material: str, style: str,
                              craft: str = "基础抛光") -> JewelryBaseInfo:
        """
        获取/创建珠宝基础信息对象(核心:先查缓存,再创建)
        :param category:
        :param material:
        :param style:
        :param craft:
        :return:
        """
        # 内部状态组合作为唯一键(保证相同状态的对象只创建一次)
        key = (category, material, style, craft)
 
        if key not in cls._flyweight_pool:
            # 无缓存时创建新对象
            cls._flyweight_pool[key] = JewelryBaseInfo(category, material, style, craft)
            print(f"【工厂】创建新基础信息对象:{key}")
        else:
            print(f"【工厂】复用已有基础信息对象:{key}")
 
        return cls._flyweight_pool[key]
 
    @classmethod
    def get_pool_size(cls) -> int:
        """
        查看缓存池大小(验证共享效果)
        :return:
        """
        return len(cls._flyweight_pool)
代码语言:javascript
复制
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:享元模式 Flyweight Pattern
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/3/5 22:45
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : JewelryInventory.py
from FlyweightPattern.JewelryBaseInfo import JewelryBaseInfo
from dataclasses import dataclass
 
# -------------------------- 3. 业务实体(依赖享元对象,包含外部状态) --------------------------
@dataclass
class JewelryInventory:
    """
    珠宝库存实体(外部状态 + 享元对象)
    """
    base_info: JewelryBaseInfo
    """
    引用享元对象(共享内部状态)
    """
    weight: float
    """
    克重(外部状态)
    """
    size: float
    """
    尺寸(戒指圈口/项链长度,外部状态)
    """
    stock_location: str
    """
    库存位置(外部状态)
    """
    stock_quantity: int = 1
    """
    库存数量(外部状态)
    """
 
    def check_stock(self) -> str:
        """
        查询库存信息
        :return:
        """
        return (
            f"【库存查询】\n"
            f"  基础信息:{self.base_info.get_base_desc()}\n"
            f"  个性化信息:克重{self.weight}g | 尺寸{self.size}mm | 库存位置{self.stock_location} | 库存数量{self.stock_quantity}件"
        )
 
 
 
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:享元模式 Flyweight Pattern
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/3/5 22:47
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : SalesOrder.py
 
from FlyweightPattern.JewelryBaseInfo import JewelryBaseInfo
from dataclasses import dataclass
 
# -------------------------- 3. 业务实体(依赖享元对象,包含外部状态) --------------------------
 
@dataclass
class SalesOrder:
    """
    销售订单实体(外部状态 + 享元对象)
    """
    base_info: JewelryBaseInfo
    """
    引用享元对象(共享内部状态)
    """
    weight: float
    """
    克重(外部状态)
    """
    size: float
    """
    尺寸(外部状态)
    """
    order_no: str
    """
    订单号(外部状态)
    """
    customer_name: str
    """
    客户姓名(外部状态)
    """
    price: float
    """
    成交价格(外部状态)
    """
 
    def create_order(self) -> str:
        """
        生成销售订单
        :return:
        """
        return (
            f"【销售订单】\n"
            f"  订单号:{self.order_no}\n"
            f"  客户:{self.customer_name}\n"
            f"  商品:{self.base_info.get_base_desc()}\n"
            f"  规格:克重{self.weight}g | 尺寸{self.size}mm\n"
            f"  成交金额:¥{self.price:.2f}"
        )
代码语言:javascript
复制
# encoding: utf-8
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:享元模式 Flyweight Pattern
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2024.3.6 python 3.11
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/3/5 22:50
# User      :  geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : FlyweightBll.py
 
from FlyweightPattern.JewelryFlyweightFactory import JewelryFlyweightFactory
from FlyweightPattern.JewelryInventory import JewelryInventory
from FlyweightPattern.SalesOrder import SalesOrder
 
 
# -------------------------- 4. 客户端业务流程(模拟珠宝店实际操作) --------------------------
class FlyweightBll(object):
    """
 
    """
    def demo(self):
        """
 
        :return:
        """
        # 1. 初始化享元工厂
        factory = JewelryFlyweightFactory()
 
        # 2. 场景1:添加多款「足金999 传承系列 戒指」到库存(仅外部状态不同,共享基础信息)
        print("===== 库存操作 =====")
        # 第1枚传承戒指(创建新享元对象)
        base_ring1 = factory.get_jewelry_base_info("戒指", "足金999", "传承系列")
        inventory_ring1 = JewelryInventory(base_ring1, 5.2, 18.0, "A区1层01柜", 5)
        print(inventory_ring1.check_stock())
 
        # 第2枚传承戒指(复用已有享元对象)
        base_ring2 = factory.get_jewelry_base_info("戒指", "足金999", "传承系列")
        inventory_ring2 = JewelryInventory(base_ring2, 5.5, 19.0, "A区1层01柜", 3)
        print(inventory_ring2.check_stock())
 
        # 3. 场景2:添加「铂金PT950 小蛮腰 项链」到库存
        base_necklace1 = factory.get_jewelry_base_info("项链", "铂金PT950", "小蛮腰", "拉丝工艺")
        inventory_necklace1 = JewelryInventory(base_necklace1, 8.8, 45.0, "B区2层05柜", 2)
        print(inventory_necklace1.check_stock())
 
        # 4. 场景3:销售珠宝(基于库存创建订单,复用享元对象)
        print("\n===== 销售操作 =====")
        # 销售1枚传承戒指
        order1 = SalesOrder(
            base_info=base_ring1,
            weight=5.2,
            size=18.0,
            order_no="SO20260305001",
            customer_name="张三",
            price=5.2 * 600  # 假设金价600元/克
        )
        print(order1.create_order())
 
        # 销售1条小蛮腰项链
        order2 = SalesOrder(
            base_info=base_necklace1,
            weight=8.8,
            size=45.0,
            order_no="SO20260305002",
            customer_name="李四",
            price=8.8 * 400  # 假设铂金400元/克
        )
        print(order2.create_order())
 
        # 5. 验证享元对象数量(仅2个:传承戒指、小蛮腰项链)
        print(f"\n===== 享元池统计 =====")
        print(f"当前缓存的珠宝基础信息对象数量:{factory.get_pool_size()}")

调用:

代码语言:javascript
复制
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: 设计模式 Design Patterns
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2026/2/18 20:58
# User      : geovindu
# Product   : PyCharm
# Project   : pydesginpattern
# File      : main.py
# explain   : 学习
 
import bll.CheckPatterns
 
 
def select_design_pattern() -> tuple[int, bll.CheckPatterns.DesignPattern | None]:
    """
    返回 (序列号, 选中的枚举对象),退出则返回 (0, None)
    :return:
    """
    print("\n=== 方式3:用户选择展示 ===")
    print("可选设计模式(输入0或q退出):")
    for idx, pattern in enumerate(bll.CheckPatterns.DesignPattern, 1):
        print(f"{idx}. {pattern._name_to_cn(pattern.name)}({pattern.name})")
    print("0. 退出")
 
    while True:
        user_input = input("\n请输入序号选择要展示的设计模式(输入0/q退出):").strip()
        if user_input in ("0", "q", "Q"):
            print("👋 退出选择流程")
            return (0, None)
 
        try:
            choice = int(user_input)
            if 1 <= choice <= len(bll.CheckPatterns.DesignPattern):
                selected_pattern = list(bll.CheckPatterns.DesignPattern)[choice - 1]
                print(f"✅ 你选择了序号:{choice}(对应{selected_pattern._name_to_cn(selected_pattern.name)})")
                return (choice, selected_pattern)  # 返回(序列号, 枚举对象)
            else:
                print(f"❌ 输入无效!请输入1-{len(bll.CheckPatterns.DesignPattern)}之间的数字,或0/q退出")
        except ValueError:
            print("❌ 输入无效!请输入数字序号,或0/q退出")
 
def ask_continue() -> bool:
    """
    询问用户是否继续选择,返回True(继续)/False(退出)
    """
    while True:
        user_choice = input("\n是否继续选择其他设计模式?(y/n):").strip().lower()
        if user_choice == "y":
            return True
        elif user_choice == "n":
            print("👋 感谢使用,程序结束!")
            return False
        else:
            print("❌ 输入无效!请输入 y(继续)或 n(退出)")
 
 
if __name__ == '__main__':
 
    # 方式1:用户输入选择展示(交互版)
    '''
    print("\n=== 方式1:用户选择展示 ===")
    print("可选设计模式:")
    for idx, pattern in enumerate( bll.CheckPatterns.DesignPattern, 1):
        print(f"{idx}. {pattern._name_to_cn(pattern.name)}({pattern.name})")
 
    try:
        choice = int(input("\n请输入序号选择要展示的设计模式:"))
        selected_pattern = list( bll.CheckPatterns.DesignPattern)[choice - 1]
        selected_pattern.show_example()
    except (ValueError, IndexError):
        print("❌ 输入无效,请输入正确的序号!")
    '''
    # 2
 
    print("🎉 设计模式示例展示程序")
    while True:
        # 1. 选择设计模式
        selected_num, selected_pattern = select_design_pattern()
 
        # 2. 判断是否直接退出(输入0/q)
        if selected_num == 0:
            print("👋 程序结束!")
            break
 
        # 3. 执行选中的示例
        selected_pattern.show_example()
        print(f"\n📌 本次选择的序列号是:{selected_num}")
 
        # 4. 询问是否继续
        if not ask_continue():
            break  # 用户选择不继续,终止循环
 
    print('hi,welcome geovindu.')

输出:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档