Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 有没有好的设计模式或解决方案来处理状态之间存在依赖关系的转换行为?_Design Patterns - Fatal编程技术网

Design patterns 有没有好的设计模式或解决方案来处理状态之间存在依赖关系的转换行为?

Design patterns 有没有好的设计模式或解决方案来处理状态之间存在依赖关系的转换行为?,design-patterns,Design Patterns,假设有如下四种状态 A state B state C state D state A is default state B is C,D state's precondition C is D state's precondition 还有一个复杂的转换依赖项,如下所示 A state B state C state D state A is default state B is C,D state's precondition C is D state's precondition

假设有如下四种状态

A state
B state
C state
D state
A is default state
B is C,D state's precondition
C is D state's precondition
还有一个复杂的转换依赖项,如下所示

A state
B state
C state
D state
A is default state
B is C,D state's precondition
C is D state's precondition
目前,我的想法如下

if(conditionXXX){
 state = B;
}
else if(B && conditionYYY) {
 state = C;
}
else if(C && conditionZZZ) {
 state = D;
}
else {
 state = A;
}
但我认为这不是一个好的解决方案。
有什么好的设计模式或解决方案吗?

无论您选择什么样的范例,在这种情况下,您可能想要的是状态的模块化(我不是故意使用封装)。这意味着每个状态都应该是合理的自包含的,在这种情况下,只知道要转换到的状态的某种ID以及条件

我们可以通过多种方式对此进行建模,但通常最好从最简单、最直接的方法开始

type StateId = String
type Transition = Context -> Maybe StateId
data State = State { transition :: Transition, action :: Action, id :: StateId }
在本例中,我不提供
操作
上下文
的类型,因为它们最终取决于您希望如何获得
条件xxx/YYY/ZZZ
以及在给定状态下您希望做什么

转换的类型
意味着每个状态都需要提供一些逻辑来确定它是否可以移动到另一个状态

表达你的逻辑,那就是:

stateA = State { transition = \ctx -> if conditionXXX ctx then Just "B" else Nothing, action = (), id = "A" }

stateB = State { transition = \ctx -> if conditionYYY ctx then Just "C" else Nothing, action = (), id = "B" }

stateC = State { transition = \ctx -> if conditionZZZ ctx then Just "D" else Nothing, action = (), id = "C" }

stateD = State { transition = Just "A", action = (), id = "D" }
请注意,您不必检查所处的状态,因为这些函数位于状态值内这一事实暗示了这一点

有了这些,我们只需要存储状态:

data StateMachine = StateMachine { states :: [State], currentState :: State }

sm = StateMachine [stateA, stateB, stateC, stateD] stateA
现在转换函数需要能够询问当前状态是否可以转换:

transition :: Context -> StateMachine -> StateMachine
transition context sm = 
    case transition (currentState sm) $ context of
        Nothing -> sm
        Just newStateId -> {- find the State associated with id and change currentState }

我选择Haskell作为这个示例实现,但是您当然可以用任何语言编写它。他们的关键思想是,从
transition
StateMachine
的角度来看,状态集合是开放的,您可以自由地将它们添加和删除到机器中。

感谢您的详细回答。如果解释是C++语言,我会很容易理解。如果你知道类似的C++例子,请告诉我: