设计模式:责任链模式(Chain of Responsibility)

责任链模式是行为模式中的一种。它允许将请求沿着潜在处理者链传递,直到其中一个处理者处理该请求。

它具有以下核心特点:

- 业务逻辑由多个独立环节组成,各环节没有特定顺序的要求(但是也可以是特定的顺序);

- 各环节处理逻辑相对独立,不依赖其他环节的处理逻辑;

- 不强制要求前序环节必须成功;

- 任一环节可自主决定是否中止流程。

在标准情况下,责任链模式需要一个接口和一个抽象类。但是在 VFP 中,虽然可以通过类模板模拟接口并通过技巧阻止类的实例化,基于我对 VFP 的理解,它们应该是可以合二为一的。也就是具体的环节处理都有单独的类来实现;而所有环节中执行单独逻辑的类,拥有一个共同的父类(抽象类):

代码语言:javascript代码运行次数:0运行复制
Define Class AbstractHandler As Custom
	oNextHandler = .Null.

	*** <summary>
	*** 模拟抽象类,禁止实例化
	*** </summary>
        Procedure Init()
            Return .F.
        Endproc

	*** <summary>
	*** 设置下一个环节所使用的处理者
	*** </summary>
	*** <param name="toHandler">下一个处理者</param>
	*** <returns>处理者本身,以便可以进行链式调用。</returns>
	*** <remarks>
	*** 你可以通过调用一个处理者的方法来设置其下一个处理者。
	*** 注意,你可以将请求处理者设置为自身,从而形成一个环。
	*** </remarks>
        Procedure SetNext(toHandler As AbstractHandler) As AbstractHandler
            This.oNextHandler = m.toHandler

            Return m.toHandler
        Endproc

	*** <summary>
	*** 处理者通常会对其请求进行一些处理,然后将其传递给下一个处理者。
	*** 或者,对于最终处理者,它可能会处理请求。
	*** </summary>
	*** <param name="toRequest">包含请求的对象</param>
	*** <remarks>
	*** 子类可以重写该方法,但通常它应该至少调用父类的方法。
	*** 这样,每个处理者都可以访问其下一个处理者。
	*** </remarks>
        Procedure Handle(toRequest As Object) As Object
            If This.oNextHandler <> .Null.
                This.oNextHandler.Handle(m.toRequest)
            Endif

            Return .Null.
        Endproc
Enddefine

假设存在两个环节:

代码语言:javascript代码运行次数:0运行复制
Define Class StepOne as AbstractHandler
        Procedure Init
		NoDefault
	EndProc 

        Procedure Handle(toRequest As Object) As Object
		If 条件 = .T.
                    Return 结果
		EndIf 

              Return DoDefault(m.toRequest)
	EndProc 
EndDefine

Define Class StepTwo as AbstractHandler
        Procedure Init
		NoDefault
	EndProc 

        Procedure Handle(toRequest As Object) As Object
		If 条件 = .T.
                    Return 结果
		EndIf 

              Return DoDefault(m.toRequest)
	EndProc 
EndDefine

这样,我们的代码大概就类似于下面的样子:

代码语言:javascript代码运行次数:0运行复制
*!* 假设存在包含请求的对象 loRequest
Local loStepOne as StepOne, loStepTwo as StepTwo
m.loStepOne		= CreateObject("StepOne")
m.loStepTwo		= CreateObject("StepTwo")
*!* m.loStepThree	= CreateObject("StepThree")

*!* 构造责任链
m.loStepOne.SetNext(m.loStepTwo)
*!* m.loStepTwo.SetNext(m.loStepThree)

m.loStepOne.Handle(m.loRequest)

尽管责任链模式可以用于特定顺序的业务逻辑,但是针对特定的处理顺序,责任链模式未必是最佳选择。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-28,如有侵权请联系 cloudcommunity@tencent 删除接口设计模式procedure对象技巧