用 Strategy 类替代硬编码 if-else 可解耦“做什么”与“怎么做”,通过字典映射实现运行时策略选择,配合 @cached_property 缓存实例、严格输入校验与兜底处理,提升可维护性、可测试性与扩展性。

用 Strategy 类替代硬编码的 if-else 分支
当 Django 视图或服务层中出现大量基于请求参数、用户角色、业务状态等条件判断时,直接写 if/elif/else 会迅速让函数膨胀、难以测试、违反开闭原则。策略模式的核心是把“做什么”和“怎么做”解耦——每个分支逻辑封装成独立类,主流程只负责选策略、执行策略。
常见场景:订单支付方式路由、内容审核规则、报表导出格式选择、权限校验链路。
- 每个策略类必须实现统一接口(如
execute()或handle()),接受相同签名的参数 - 策略实例不应在每次调用时新建,建议通过工厂方法或依赖注入管理生命周期
- 避免在策略内部再嵌套 if-else;如果策略本身逻辑复杂,应进一步拆解为子策略或组合调用
注册策略到 dict 映射表,而不是写 if-else 链
Django 中最轻量、最实用的策略落地方式,就是用 dict 做运行时查找表。它比反射更安全,比 getattr() 更可控,也比硬编码 if 更易维护。
示例:根据 report_type 参数决定导出行为
# strategies.py
class CSVExporter:
def handle(self, data): return generate_csv(data)
<p>class ExcelExporter:
def handle(self, data): return generate_excel(data)</p><p>class PDFExporter:
def handle(self, data): return generate_pdf(data)</p><p>EXPORT_STRATEGIES = {
'csv': CSVExporter(),
'xlsx': ExcelExporter(),
'pdf': PDFExporter(),
}
</p>
视图中直接查表调用:
# views.py
def export_report(request):
report_type = request.GET.get('type')
strategy = EXPORT_STRATEGIES.get(report_type)
if not strategy:
raise Http404("Unsupported export type")
return strategy.handle(query_data())
- 新增类型只需加一个类 + 注册进
EXPORT_STRATEGIES,不碰原有逻辑 - 映射键(如
'csv')建议与 API 参数值严格一致,避免额外转换 - 不要用
globals()或importlib.import_module()动态加载策略类——调试困难、IDE 不识别、热重载易出错
在 Django 中用 @cached_property 缓存策略实例
如果策略对象构造开销大(比如要初始化数据库连接、加载配置、解析模板),又或者被频繁调用(如中间件、信号处理),重复创建会浪费资源。Django 的 @cached_property 是天然解法。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
示例:不同租户使用不同风控策略
# services.py
class TenantRiskService:
def __init__(self, tenant_id):
self.tenant_id = tenant_id
<pre class="brush:php;toolbar:false;">@cached_property
def strategy(self):
config = TenantConfig.objects.get(id=self.tenant_id)
if config.risk_level == 'high':
return HighRiskStrategy()
elif config.risk_level == 'medium':
return MediumRiskStrategy()
else:
return LowRiskStrategy()
-
@cached_property确保每个实例只计算一次,且线程安全(Django 4.2+) - 不要在
__init__中直接 new 策略对象——无法享受缓存,也无法延迟加载 - 若策略需传参(如当前用户、请求上下文),应改用普通方法 + 手动缓存字典,因为
@cached_property不支持参数
别忽略策略的边界检查和 fallback 处理
策略模式不是万能胶。实际项目里最常踩的坑,是忘了验证输入合法性、没设兜底策略、或把错误处理全扔给上层。
- 映射表查不到 key 时,
.get(key)返回None,必须显式判空并抛出语义明确的异常(如NotImplementedError或自定义UnsupportedStrategyError) - 策略类的
handle()方法应统一约定返回值类型和错误行为;避免有的返回HttpResponse,有的返回dict,有的又抛异常 - 对关键路径(如支付、审核),建议加日志记录所用策略名,方便线上问题定位:“used strategy=
AliPayStrategyfor order_id=12345”
策略越细,越容易漏掉异常分支。真正难的不是写策略,而是定义清楚每个策略的职责边界和失败时该交由谁兜底。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










