按照标准的描述,该模式“让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。”
从组成上来看,它仅需要一个上下文类和策略类。如果你有大量复杂的条件语句,那么,你可能需要使用该设计模式。
该设计模式也和其他设计模式一样,同样存在一些缺点:
所以,该模式在 VFP 中应用的难度并不在于它的实现,而在于在何种情况下取代大量复杂的条件语句。这需要一些平衡。
如果使用最简示例来演示的话,那么常规情况下的这段代码足够了:
Local lcCurrentState As String
m.lcCurrentState = "A"
Do Case
Case m.lcCurrentState = "A"
*!* 一些语句
m.lcCurrentState = "B"
Case m.lcCurrentState = "B"
*!* 一些语句
m.lcCurrentState = "A"
Endcase
如果你的所有相关代码与此类似,那么,你很幸运。但是,如果有更多的 Case 分支呢?如果在多处存在雷同的 Case 分支呢?如果在相似但不同的业务逻辑中存在这样的情况呢?好吧,一旦需求有所变动,那么,你就可以开始做一个小小的噩梦了
如果要将上述代码转换为状态模式下的实现,那么,首先需要一个所谓的策略类模板:
Define Class State As Custom
oContext = .Null.
Procedure SetContext(toContext As Object)
This.oContext = m.toContext
EndProc
Procedure RequeryA()
Endproc
Procedure RequeryB()
Endproc
Enddefine
然后,你可以继承该类建立相应的状态类:
Define Class StateA As State
tag = "A"
Procedure RequeryA()
*!* 一些处理语句
This.oContext.TransitionTo(CreateObject("StateB"))
Endproc
EndDefine
Define Class StateB As State
tag = "B"
Procedure RequeryB()
*!* 一些处理语句
This.oContext.TransitionTo(CreateObject("StateA"))
Endproc
EndDefine
因此,所谓的上下文类就可以这样定义:
Define Class Context As Custom
oState = .NULL.
Procedure Init(toState As Object)
This.oState = m.toState
Endproc
Procedure TransitionTo(toState As Object)
This.oState = m.toState
This.oState.SetContext(This)
Endproc
Procedure RequeryA()
This.oState.RequeryA()
Endproc
Procedure RequeryB()
This.oState.RequeryB()
Endproc
Enddefine
最后,我们的代码就变成了:
Local loContext As Context
m.loContext = CreateObject("Context", CreateObject("StateA"))
m.loContext.RequeryA()
m.loContext.RequeryB()
在以上的代码中需要注意以下两点:
未完待续......