问题
每个人、事物在不同的状态下会有不同表现(动作),而一状态又会在不同的表现下转移到下一个不同的状态(State)。最简单的一个生活中的例子就是:地铁入口处,如果你放入正确的地铁票,门就会打开通过,在出口处验票,如果正确就可以ok,否则就不让你通过(如果动作野蛮,或许会有报警(Alarm)
有限状态自动机(FSM)也是一个典型的状态不同,对输入有不同的响应(状态转移)。通常我们在实现这类系统会使用到很多的Switch/Case语句,Case某种状态,发生什么动作,Case另外一种状态,则发生另外一种状态,但是这种实现方式至少有以下两个问题:
(1)当状态数目很多时,维护一大组Switch/Case语句将是一件异常困难并且容易出错的事情。
(2)状态逻辑和动作实现没有分离。在很多的系统实现中,动作的实现代码直接写在状态的逻辑当中。这带来的后果就是系统的扩展性和维护得不到保证。
结构图
State PatternState模式就是被用来解决上面列出的两个问题的,在State模式中我们将状态逻辑和动作实现进行分离。当一个操作中要维护大量的Case分支语言,并且这些分支依赖于对象的状态。State模式将每一个分支都封装到独立的类中。
State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
讨论
State 模式和 Strategy 模式又很大程度上的相似: 它们都有一个 Context 类, 都是通过委托(组合) 给一个具有多个派生类的多态基类实现Context 的算法逻辑。 两者最大的差别就是State 模式中派生类持有指向 Context 对象的引用,并通过这个引用调用 Context 中的方法,但在Strategy 模式中就没有这种情况。因此可以说一个 State 实例同样是 Strategy 模式的一个实例,反之却不成立。实际上State 模式和 Strategy 模式的区别还在于它们所关注的点不尽相同:
State 模式主要是要适应对象对于状态改变时的不同处理策略的实现,而 Strategy则主要是具体算法和实现接口的解耦( coupling), Strategy 模式中并没有状态的概念(虽然很多时候有可以被看作是状态的概念),并且更加不关心状态的改变了。
State 模式很好地实现了对象的状态逻辑和动作实现的分离, 状态逻辑分布在 State 的派生类中实现,而动作实现则可以放在Context 类中实现(这也是为什么 State 派生类需要拥有一个指向Context 的指针)。 这使得两者的变化相互独立, 改变 State 的状态逻辑可以容易复用Context 的动作, 也可以在不影响 State 派生类的前提下创建 Context 的子类来更改或替换动作实现。State 模式问题主要是逻辑分散化, 状态逻辑分布到了很多的 State 的子类中, 很难看到整个的状态逻辑图,这也带来了代码的维护问题。
网友评论