策略组合实践
前置:能区分接口契约与实现,理解函数作为参数和整数分计价;Python 3.10+ 仅用于报价模型。教学范围为函数组合与GoF意图;Python 3.10+。核对日期2026-10-17。示例未执行,本轮没有安装依赖、生成协议代码、启动服务或浏览器预览。完整源码和输入文件见下方「同源完整文件」;推演结论只适用于写明的模型。
完整报价组合程序
完整报价组合程序把折扣和报价校验分离,整数分避免二进制浮点金额误差。普通价、九折和满额减20元各为独立函数;上下文验证策略输出,不执行收费。输入数量和单价不能为负,未知策略显式失败。
策略输出与异常
策略输出与异常可以逐项核对:单价1000分数量3得到普通价3000分、九折2700分;满额门槛是10000分。采用整数除法向下取整是本教学规则,生产税费的舍入方式应单独确定,不能默默继承。
设计模式取舍练习
设计模式取舍练习把满额阈值从10000改为12000,应只改变策略中的阈值,而不改变输入验证。加入返回负数的测试替身,检查上下文是否拒绝非法结果;这验证的是契约,不是多写一个接口。
同源完整文件
以下README含前置、输入、读者自跑步骤、预期结果、失败、恢复与清理;只做静态核对,没有执行。
model.py
python
import json
import sys
def regular(total):
return total
def ten_percent_off(total):
return total * 90 // 100
def threshold_off(total):
return total - 2000 if total >= 10000 else total
POLICIES = {'regular': regular, 'discount': ten_percent_off, 'threshold': threshold_off}
def quote(price, quantity, policy):
if type(price) is not int or type(quantity) is not int or price < 0 or quantity < 0:
raise ValueError('nonnegative integer cents and quantity required')
result = policy(price * quantity)
if type(result) is not int or result < 0:
raise ValueError('policy violated amount contract')
return result
if __name__ == '__main__':
try:
data = json.load(sys.stdin)
policy = POLICIES[data['policy']]
print(json.dumps({'cents': quote(data['price'], data['quantity'], policy)}))
except (ValueError, TypeError, KeyError) as error:
print(str(error), file=sys.stderr)
sys.exit(2)requirements.txt
text
# Python 3.10+ standard library only; no third-party dependency.README.md
md
# 设计模式与变化边界:完整示例
示例未执行。核对日期2026-10-17。教学版本族:函数组合与GoF意图;Python 3.10+。
## 文件与依赖
文件:model.py, requirements.txt。requirements.txt为同源依赖声明;所有代码和配置都随本文展示。本例使用 Python 3.10+ 标准库,无额外运行依赖。
## 输入与前置
前置:理解函数作为参数与策略替换,金额统一用整数分。使用 Python 3.10+,本例只依赖标准库。输入为 price、quantity 和 policy 组成的 JSON 对象;具体报价与错误预期见下节。
读者将来自跑(本轮未执行):在本目录以Python 3.10+读取input.json,PowerShell示意`Get-Content -Raw input.json | python model.py`;Bash示意`python3 model.py < input.json`。把下面输入手工保存为UTF-8文件,输出按预期逐项比较。无需安装依赖,没有服务或网络调用;程序只读标准输入并写标准输出,不改原文件。失败信息写标准错误且退出2。恢复是修正输入后重读,清理只删除自己创建的input.json与输出文件,勿递归删除工作目录。
## 预期结果、失败与恢复
输入 {"price":1000,"quantity":3,"policy":"discount"},预期cents=2700;price=5000 quantity=2 policy=threshold得到8000;未知policy退出2。
失败要保留输入和错误,先与正文的不变量及边界核对。没有真实服务或性能验证,不以这些模型输出证明生产可用性。
## 独立练习
门槛改为12000;分别手算11999、12000分。再向quote注入lambda total: -1。
参考答案:把threshold_off条件改成total>=12000,11999保持11999,12000减2000得10000。注入负数策略会被quote拒绝,说明输入正确仍须检查可替换实现的输出。先作答,再核对
门槛改为12000;分别手算11999、12000分。再向quote注入lambda total: -1。
逐步参考解答
把threshold_off条件改成total>=12000,11999保持11999,12000减2000得10000。注入负数策略会被quote拒绝,说明输入正确仍须检查可替换实现的输出。
报价管道的失败位置
按单价1000分、数量3、九折计算,原始金额3000,策略返回2700;输入校验与结果校验在不同位置。未知策略应在选择阶段失败,负数结果应在返回前失败。把这两类错误分开,才能判断应修输入还是修策略实现。
查看图表代码
来源与适用边界
- 英文官方、作者或规范原文:本专题机制依据;按上述固定版本族阅读。
- 中文官方或作者资料:用于术语和讲解交叉核对,冲突以原始规范为准。
继续阅读
- 设计意图与对象责任
- 设计意图与对象责任
- 设计意图与对象责任