基于odoo17的设计模式详解---职责模式

发布于:2025-07-07 ⋅ 阅读:(15) ⋅ 点赞:(0)

大家好,我是你的Odoo技术伙伴。在Odoo这个高度模块化的平台上,一个核心的业务流程,比如“从销售订单创建发票”,往往需要多个模块的协作。sale模块负责创建基础发票,sale_stock模块关联库存信息,自定义的sale_loyalty模块可能计算并添加忠诚度折扣。这些模块如何协作,既完成各自任务,又互不干扰、无需知晓彼此的存在?答案就是职责链模式(Chain of Responsibility Pattern)

一、什么是职责链模式?

通过一个现实世界的审批流程来理解:

假设公司有一笔费用报销申请:

  1. 申请单提交给直接经理(Handler 1)。若金额在其权限内,他批准,流程结束。
  2. 若金额超限,他不拒绝,而是将申请单传递给部门总监(Handler 2)。
  3. 总监审核,若金额在其权限内,他批准;否则,继续传递给财务副总裁(Handler 3),依此类推。

职责链模式的核心思想:避免请求的发送者和接收者耦合,让多个对象都有机会处理请求。将这些对象连成一条链,请求沿链传递,直到被处理。

  • 请求(Request):费用报销申请。
  • 处理者(Handler):经理、总监、副总裁。
  • 链(Chain):经理 -> 总监 -> 副总裁。

发送者(员工)只需将请求“扔”到链的开端,无需知道谁最终处理。

二、Odoo的精髓:super()就是那条链

在Odoo中,职责链模式通过ORM的继承机制实现,super()函数是连接这条链的关键。

  • 请求:方法调用,如sale_order._create_invoices()
  • 处理者:继承并重写该方法的每个模块中的类。
  • :由Odoo的方法解析顺序(MRO)决定的super()调用序列。

当多个模块继承同一模型并重写同一方法时,它们自动形成职责链。

场景剖析:多模块协作创建发票

目标:扩展“从销售订单创建发票”的流程。

  • 基础处理者sale模块,_create_invoices()创建基本发票。
  • 处理者Asale_project模块,为发票关联项目信息。
  • 处理者Bsale_loyalty模块,添加忠诚度折扣。
1. 基础处理者 (sale模块)
# addons/sale/models/sale_order.py
class SaleOrder(models.Model):
    _name = 'sale.order'
    
    def _create_invoices(self, grouped=False, final=False, date=None):
        # 核心逻辑:创建 account.move 并返回
        invoices = self.env['account.move'].create(invoice_vals_list)
        print("Handler: sale (Base) - Basic invoice created.")
        return invoices
2. 处理者A (sale_loyalty模块)
# addons/my_sale_loyalty/models/sale_order.py
class SaleOrderLoyalty(models.Model):
    _inherit = 'sale.order'

    def _create_invoices(self, grouped=False, final=False, date=None):
        # 先传递请求给链上的下一个处理者
        invoices = super(SaleOrderLoyalty, self)._create_invoices(grouped, final, date)
        
        # 执行自己的逻辑
        print("Handler: sale_loyalty - Checking for loyalty discounts...")
        for invoice in invoices:
            if invoice.partner_id.is_loyal:
                # 添加折扣行逻辑
                print(f"  -> Added loyalty discount to invoice {invoice.name}")
        
        return invoices
3. 处理者B (sale_project模块)

假设sale_project依赖sale_loyalty

# addons/my_sale_project/models/sale_order.py
class SaleOrderProject(models.Model):
    _inherit = 'sale.order'

    def _create_invoices(self, grouped=False, final=False, date=None):
        # 先传递请求
        invoices = super(SaleOrderProject, self)._create_invoices(grouped, final, date)

        # 执行自己的逻辑
        print("Handler: sale_project - Linking project to invoice...")
        for invoice in invoices.filtered(lambda inv: inv.order_id.project_id):
            invoice.project_id = inv.order_id.project_id
            print(f"  -> Linked project to invoice {invoice.name}")
        
        return invoices

链的执行顺序

当用户点击“创建发票”:

  1. 由于sale_project依赖sale_loyalty,MRO为[SaleOrderProject, SaleOrderLoyalty, SaleOrder, ...]
  2. super()调用链:
    • SaleOrderProject._create_invoices()调用super()
    • 请求传递至SaleOrderLoyalty._create_invoices(),它调用super()
    • 请求传递至SaleOrder._create_invoices(),创建基础发票,返回invoices
    • SaleOrderLoyalty接收invoices,添加折扣,返回修改后的invoices
    • SaleOrderProject接收invoices,关联项目信息,返回最终结果。

输出日志

Handler: sale_project - Linking project to invoice...
Handler: sale_loyalty - Checking for loyalty discounts...
Handler: sale (Base) - Basic invoice created.
  -> Added loyalty discount to invoice INV/2023/0001
  -> Linked project to invoice INV/2023/0001

(注:打印顺序与执行顺序相反,因printsuper()之后)

三、职责链模式的优势与注意事项

优势

  1. 终极解耦:模块间完全解耦,可随时安装/卸载模块,系统仍正常运行。
  2. 高度可扩展:新增处理者(如sale_commission模块)只需继承模型、重写方法、调用super()
  3. 单一职责:每个模块的逻辑封装在自己的方法中,职责清晰,易维护。

注意事项

  1. super()是生命线:若忘记调用super(),链中断,上游逻辑被跳过,可能导致严重bug。
  2. 顺序可能重要:模块依赖关系决定MRO,需仔细设计(如先计算总额再折扣)。
  3. 请求不一定被处理:Odoo中基础方法通常确保核心处理,职责链更注重“增强”。

结论

职责链模式是Odoo模块化架构的基石,通过_inheritsuper()融入日常开发。运用此模式,扩展核心功能时:

  1. 继承相关模型。
  2. 重写目标方法。
  3. 方法首行调用super()
  4. super()返回结果进行增强。

掌握职责链模式,你将构建松耦合、高内聚、易维护的Odoo应用,领会其设计精髓。


网站公告

今日签到

点亮在社区的每一天
去签到