以珠宝门店的核心业务流程为例:
珠宝实体属性:编号、名称、类型(钻石 / 黄金 / 翡翠)、重量、价格、库存、鉴定证书编号
核心业务流程:
查询指定编号的珠宝信息
计算珠宝的折后价(会员折扣)
生成珠宝的销售单据
扣减珠宝库存(销售后)
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 20:55
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : Jewelry.py
from abc import ABC, abstractmethod
from typing import Optional
# 1:---定义珠宝接口(统一真实对象和空对象的行为)
# 珠宝实体接口(定义核心行为)
class Jewelry(ABC):
"""
珠宝实体属性(抽象属性,强制子类实现)
"""
@property
@abstractmethod
def id(self) -> str:
"""
珠宝编号
:return:
"""
pass
@property
@abstractmethod
def name(self) -> str:
"""
珠宝名称
:return:
"""
pass
@property
@abstractmethod
def type(self) -> str:
"""
珠宝类型
:return:
"""
pass
@property
@abstractmethod
def weight(self) -> float:
"""
重量
:return:
"""
pass
@property
@abstractmethod
def price(self) -> float:
"""
原价
:return:
"""
pass
@property
@abstractmethod
def stock(self) -> int:
"""
:return:
"""
pass
@property
@abstractmethod
def certificate_id(self) -> Optional[str]:
"""
鉴定证书
:return:
"""
pass
# 业务流程方法(抽象方法,强制子类实现)
@abstractmethod
def calculate_discounted_price(self, discount: float = 0.95) -> float:
"""
计算折后价(默认会员95折)
:param discount:
:return:
"""
pass
@abstractmethod
def generate_sales_doc(self, customer_name: str) -> str:
"""
生成销售单据
:param customer_name:
:return:
"""
pass
@abstractmethod
def reduce_stock(self, quantity: int = 1) -> bool:
"""
扣减库存
:param quantity:
:return:
"""
pass
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 20:56
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : RealJewelry.py
from Model.NullObject.Jewelry import Jewelry
from typing import Optional
# ---2:实现真实珠宝对象(真实业务逻辑)
class RealJewelry(Jewelry):
"""
实现真实珠宝对象
"""
def __init__(self, id: str, name: str, type: str, weight: float, price: float, stock: int, certificate_id: Optional[str] = None):
"""
初始化珠宝实体属性
:param id:珠宝编号
:param name:珠宝名称
:param type:珠宝类型
:param weight:重量
:param price:原价
:param stock:折后价
:param certificate_id:鉴定证书编号
"""
self._id = id
self._name = name
self._type = type
self._weight = weight
self._price = price
self._stock = stock
self._certificate_id = certificate_id
# 实现实体属性的getter
@property
def id(self) -> str:
"""
珠宝编号
:return:
"""
return self._id
@property
def name(self) -> str:
"""
珠宝名称
:return:
"""
return self._name
@property
def type(self) -> str:
"""
珠宝类型
:return:
"""
return self._type
@property
def weight(self) -> float:
"""
重量
:return:
"""
return self._weight
@property
def price(self) -> float:
"""
原价
:return:
"""
return self._price
@property
def stock(self) -> int:
"""
折后价
:return:
"""
return self._stock
@property
def certificate_id(self) -> Optional[str]:
"""
鉴定证书
:return:
"""
return self._certificate_id
# 实现业务流程方法
def calculate_discounted_price(self, discount: float = 0.95) -> float:
"""
计算折后价:原价 * 折扣(最低8折)
:param discount:
:return:
"""
if discount < 0.8:
discount = 0.8
return round(self._price * discount, 2)
def generate_sales_doc(self, customer_name: str) -> str:
"""
生成销售单据(包含珠宝所有属性)
:param customer_name:
:return:
"""
doc = f"""
珠宝销售单
----------
客户姓名:{customer_name}
珠宝编号:{self._id}
珠宝名称:{self._name}
珠宝类型:{self._type}
重量(克):{self._weight}
原价(元):{self._price}
折后价(元):{self.calculate_discounted_price()}
鉴定证书编号:{self._certificate_id or '无'}
销售日期:2026-03-08
----------
"""
return doc
def reduce_stock(self, quantity: int = 1) -> bool:
"""
扣减库存:库存充足则扣减,返回True;否则返回False
:param quantity:
:return:
"""
if self._stock >= quantity:
self._stock -= quantity
return True
return False
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 20:56
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : RealJewelry.py
from Model.NullObject.Jewelry import Jewelry
from typing import Optional
# ---2:实现真实珠宝对象(真实业务逻辑)
class RealJewelry(Jewelry):
"""
实现真实珠宝对象
"""
def __init__(self, id: str, name: str, type: str, weight: float, price: float, stock: int, certificate_id: Optional[str] = None):
"""
初始化珠宝实体属性
:param id:珠宝编号
:param name:珠宝名称
:param type:珠宝类型
:param weight:重量
:param price:原价
:param stock:折后价
:param certificate_id:鉴定证书编号
"""
self._id = id
self._name = name
self._type = type
self._weight = weight
self._price = price
self._stock = stock
self._certificate_id = certificate_id
# 实现实体属性的getter
@property
def id(self) -> str:
"""
珠宝编号
:return:
"""
return self._id
@property
def name(self) -> str:
"""
珠宝名称
:return:
"""
return self._name
@property
def type(self) -> str:
"""
珠宝类型
:return:
"""
return self._type
@property
def weight(self) -> float:
"""
重量
:return:
"""
return self._weight
@property
def price(self) -> float:
"""
原价
:return:
"""
return self._price
@property
def stock(self) -> int:
"""
折后价
:return:
"""
return self._stock
@property
def certificate_id(self) -> Optional[str]:
"""
鉴定证书
:return:
"""
return self._certificate_id
# 实现业务流程方法
def calculate_discounted_price(self, discount: float = 0.95) -> float:
"""
计算折后价:原价 * 折扣(最低8折)
:param discount:
:return:
"""
if discount < 0.8:
discount = 0.8
return round(self._price * discount, 2)
def generate_sales_doc(self, customer_name: str) -> str:
"""
生成销售单据(包含珠宝所有属性)
:param customer_name:
:return:
"""
doc = f"""
珠宝销售单
----------
客户姓名:{customer_name}
珠宝编号:{self._id}
珠宝名称:{self._name}
珠宝类型:{self._type}
重量(克):{self._weight}
原价(元):{self._price}
折后价(元):{self.calculate_discounted_price()}
鉴定证书编号:{self._certificate_id or '无'}
销售日期:2026-03-08
----------
"""
return doc
def reduce_stock(self, quantity: int = 1) -> bool:
"""
扣减库存:库存充足则扣减,返回True;否则返回False
:param quantity:
:return:
"""
if self._stock >= quantity:
self._stock -= quantity
return True
return False
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 20:59
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : NullJewelry.py
from Model.NullObject.Jewelry import Jewelry
from typing import Optional
# ---3:实现空珠宝对象(替代 None,避免空指针判断)
class NullJewelry(Jewelry):
"""
空珠宝对象:所有属性返回默认值,所有方法返回无操作结果
"""
# 空对象的默认属性
@property
def id(self) -> str:
"""
珠宝编号
:return:
"""
return "NULL_JEWELRY_ID"
@property
def name(self) -> str:
"""
珠宝名称
:return:
"""
return "未找到该珠宝"
@property
def type(self) -> str:
"""
珠宝类型
:return:
"""
return "未知类型"
@property
def weight(self) -> float:
"""
重量
:return:
"""
return 0.0
@property
def price(self) -> float:
"""
原价
:return:
"""
return 0.0
@property
def stock(self) -> int:
"""
折后价
:return:
"""
return 0
@property
def certificate_id(self) -> Optional[str]:
"""
鉴定证书
:return:
"""
return None
def calculate_discounted_price(self, discount: float = 0.95) -> float:
"""
空对象的业务方法(无操作/返回默认值)
:param discount:
:return:
"""
return 0.0 # 无珠宝则折后价为0
def generate_sales_doc(self, customer_name: str) -> str:
"""
:param customer_name:
:return:
"""
return f"【错误】客户{customer_name}:未找到对应珠宝,无法生成销售单"
def reduce_stock(self, quantity: int = 1) -> bool:
"""
:param quantity:
:return:
"""
return False # 无珠宝则扣减库存失败
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 21:01
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : JewelryWarehouse.py
from Interface.NullObject.NullJewelry import NullJewelry
from Model.NullObject.Jewelry import Jewelry
from Model.NullObject.RealJewelry import RealJewelry
# ----4:珠宝仓库(业务入口,使用空对象模式)
class JewelryWarehouse:
"""
珠宝仓库:管理珠宝库存,提供查询珠宝的接口
"""
def __init__(self):
"""
"""
# 模拟珠宝库存数据
self.jewelry_list = [
RealJewelry(
id="J001",
name="18K金钻石戒指",
type="钻石",
weight=3.2,
price=15800.0,
stock=5,
certificate_id="GIC20260308001"
),
RealJewelry(
id="J002",
name="足金项链",
type="黄金",
weight=12.5,
price=680.0 * 12.5, # 黄金按克计价
stock=10,
certificate_id="GIC20260308002"
),
RealJewelry(
id="J003",
name="冰种翡翠手镯",
type="翡翠",
weight=58.8,
price=89800.0,
stock=2,
certificate_id="GIC20260308003"
)
]
def find_jewelry_by_id(self, jewelry_id: str) -> Jewelry:
"""
查询珠宝:找到则返回RealJewelry,否则返回NullJewelry(而非None)
:param jewelry_id:
:return:
"""
for jewelry in self.jewelry_list:
if jewelry.id == jewelry_id:
return jewelry
# 核心:用NullJewelry替代None
return NullJewelry()
python
# encoding: utf-8
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:空对象模式(Null Object 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/9 21:03
# User : geovindu
# Product : PyCharm
# Project : pydesginpattern
# File : NullObjectBll.py
from abc import ABC
from NullObjectPattern.JewelryWarehouse import JewelryWarehouse
# ----5:业务流程测试(对比有无空对象模式的差异)
class NullObjectBll(object):
"""
"""
def demo(self):
"""
:return:
"""
# 初始化仓库
warehouse = JewelryWarehouse()
# 场景1:查询存在的珠宝(J001),执行完整业务流程
print("=== 场景1:查询存在的珠宝(J001)===")
jewelry1 = warehouse.find_jewelry_by_id("J001")
print(f"珠宝名称:{jewelry1.name}")
print(f"原价:{jewelry1.price} 元")
print(f"会员折后价:{jewelry1.calculate_discounted_price()} 元")
print(f"扣减库存前:{jewelry1.stock}")
print(f"扣减库存结果:{jewelry1.reduce_stock()}")
print(f"扣减库存后:{jewelry1.stock}")
print("销售单据:")
print(jewelry1.generate_sales_doc("张三"))
# 场景2:查询不存在的珠宝(J999),使用空对象避免空指针
print("\n=== 场景2:查询不存在的珠宝(J999)===")
jewelry2 = warehouse.find_jewelry_by_id("J999")
# 无需判断jewelry2是否为None,直接调用方法即可
print(f"珠宝名称:{jewelry2.name}")
print(f"折后价:{jewelry2.calculate_discounted_price()} 元")
print(f"扣减库存结果:{jewelry2.reduce_stock()}")
print("销售单据:")
print(jewelry2.generate_sales_doc("李四"))
调用:
python
# 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 Controller.CheckPatterns
def select_design_pattern() -> tuple[int, Controller.CheckPatterns.DesignPattern | None]:
"""
返回 (序列号, 选中的枚举对象),退出则返回 (0, None)
:return:
"""
print("\n=== 方式3:用户选择展示 ===")
print("可选设计模式(输入0或q退出):")
for idx, pattern in enumerate(Controller.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(Controller.CheckPatterns.DesignPattern):
selected_pattern = list(Controller.CheckPatterns.DesignPattern)[choice - 1]
print(f"✅ 你选择了序号:{choice}(对应{selected_pattern._name_to_cn(selected_pattern.name)})")
return (choice, selected_pattern) # 返回(序列号, 枚举对象)
else:
print(f"❌ 输入无效!请输入1-{len(Controller.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.')
输出:
