首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >设计模式:状态模式(State)

设计模式:状态模式(State)

作者头像
firstxinjie
发布2025-05-12 14:23:56
发布2025-05-12 14:23:56
10100
代码可运行
举报
文章被收录于专栏:X#(XSharp)X#(XSharp)
运行总次数:0
代码可运行

按照标准的描述,该模式“让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。”

从组成上来看,它仅需要一个上下文类和策略类。如果你有大量复杂的条件语句,那么,你可能需要使用该设计模式。

该设计模式也和其他设计模式一样,同样存在一些缺点:

  • 过度设计的风险;
  • 类数量的膨胀;
  • 状态间的耦合;
  • 相比于直接修改状态更大的性能开销;
  • 相比于条件语句来说更陡峭的学习曲线。

所以,该模式在 VFP 中应用的难度并不在于它的实现,而在于在何种情况下取代大量复杂的条件语句。这需要一些平衡。

如果使用最简示例来演示的话,那么常规情况下的这段代码足够了:

代码语言:javascript
代码运行次数:0
运行
复制
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 分支呢?如果在相似但不同的业务逻辑中存在这样的情况呢?好吧,一旦需求有所变动,那么,你就可以开始做一个小小的噩梦了

如果要将上述代码转换为状态模式下的实现,那么,首先需要一个所谓的策略类模板:

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

	Procedure SetContext(toContext As Object)
		This.oContext = m.toContext
	EndProc

	Procedure RequeryA()
	Endproc

	Procedure RequeryB()
	Endproc
Enddefine

然后,你可以继承该类建立相应的状态类:

代码语言:javascript
代码运行次数:0
运行
复制
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 

因此,所谓的上下文类就可以这样定义:

代码语言:javascript
代码运行次数:0
运行
复制
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

最后,我们的代码就变成了:

代码语言:javascript
代码运行次数:0
运行
复制
Local loContext As Context
m.loContext = CreateObject("Context", CreateObject("StateA"))

m.loContext.RequeryA()
m.loContext.RequeryB()

在以上的代码中需要注意以下两点:

  • 如果状态转换不是由类自身控制,那么,类之间的双向引用就不是必须的;
  • 如果按照标准的模式使用,双向引用在 VFP 语境下,就需要在类的 Destory 方法中显示的解绑。

未完待续......

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 xinjie的VFP 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档