Chalice项目50+客户定制邮件发送,选Factory模式还是Python装饰器?
邮件模板自定义场景的方案选型建议
现有装饰器方案的弊端
你当前写的硬编码判断逻辑的装饰器不适合50+组织、10~20个邮件方法的场景,核心问题如下:
- 硬编码org_id判断分支,组织数量增长后判断逻辑会爆炸,新增/修改组织规则需要改动装饰器代码,维护成本极高
- 每个邮件方法都要单独加装饰器,重复代码多,同一条组织规则需要在多个装饰器里重复编写,容易出错
- 不支持动态调整模板,修改模板内容需要改动代码重新部署,运营层面的调整灵活性极低
工厂模式的正确实现(无需为每个组织单独写类)
你对工厂模式的顾虑是常见的误解:简单工厂模式完全可以基于配置实现,不需要为每个组织定义单独的类,只要不同组织的差异仅在模板内容、没有特殊的邮件发送逻辑,就可以把所有组织的模板统一存在配置中,由工厂类统一读取返回:
class MailTemplateFactory: # 模板配置实际可从JSON配置文件、AWS Parameter Store、数据库/缓存加载,适配Chalice部署场景 # 配置格式: (org_id, 邮件类型): 模板内容 _org_templates = { (5, "welcome"): "欢迎 {{username}} 加入组织5!", (5, "bill_notify"): "尊敬的{{username}},您本月账单金额为{{amount}}元", # 新增组织模板仅需在此添加对应配置即可,无需修改业务代码 } # 全局默认模板,未匹配到组织自定义模板时返回 _default_templates = { "welcome": "亲爱的{{username}},欢迎使用我们的服务", "bill_notify": "您好{{username}},您的本月账单已出,请登录账户查看" } @classmethod def get_template(cls, org_id: int, mail_type: str) -> str: return cls._org_templates.get((org_id, mail_type), cls._default_templates[mail_type])
你的所有邮件发送方法可以直接调用工厂类获取模板,不需要修改原有方法的核心逻辑:
def send_welcome_mail(appdata: dict): # 仅需新增一行调用工厂的代码即可适配组织自定义模板 template = MailTemplateFactory.get_template(appdata["org_id"], "welcome") # 原有模板渲染、邮件发送逻辑不变 rendered_content = template.format(**appdata) # 发送邮件逻辑...
如果确实存在个别组织有特殊的邮件发送逻辑(比如需要额外加附件、自定义抄送人规则,不是仅修改模板就能满足),可以在工厂中针对这类特殊组织单独编写处理逻辑,也不需要为所有50个组织都写单独的类。
装饰器的适用场景
装饰器不是完全不能用,但是不要用你当前写的硬编码org_id的版本,可以实现可参数化的装饰器,仅用于处理个别组织的特殊钩子逻辑:
def org_specific_hook(org_id: int, hook_func): def decorator(origin_mail_func): def wrapper(appdata: dict): if appdata["org_id"] == org_id: # 执行该组织的特殊前置/后置逻辑 return hook_func(appdata, origin_mail_func) return origin_mail_func(appdata) return wrapper return decorator # 示例:给org_id=5的欢迎邮件额外加专属附件 def org5_welcome_hook(appdata: dict, origin_func): appdata["attachments"] = appdata.get("attachments", []) + ["org5_welcome_gift.pdf"] return origin_func(appdata) @org_specific_hook(org_id=5, hook_func=org5_welcome_hook) def send_welcome_mail(appdata: dict): # 原有逻辑不变 ...
最终选型建议
- 优先选择优化后的配置驱动工厂模式,解决99%的组织模板自定义需求,不需要写多个类,新增组织仅需要添加模板配置,适配你10~20个邮件方法的场景,后期维护成本极低
- 仅当个别组织存在特殊的邮件发送逻辑、无法通过更换模板满足时,再用参数化装饰器做特殊钩子处理,不要全局使用硬编码判断的装饰器
- 模板配置建议存储在可动态更新的存储介质(比如数据库、AWS Parameter Store)中,可实现不用重新部署代码就修改模板内容,灵活性更高
内容的提问来源于stack exchange,提问作者Chandresh Chahar
相关产品推荐
相关产品推荐

