代码说明
l User类型是环境角色。它的作用一是定义了客户端感兴趣的方法(购买书籍),二是拥有一个状态实例,它定义了用户的当前状态(普通会员、银会员、黄金会员还是钻石会员)。
l UserLevel类型是抽象状态角色。它的作用一是定义了和状态相关的行为的接口,二是拥有一个环境实例,用于在一定条件下修改环境角色的抽象状态。
l NormalUser、 SilverUser、GoldUser以及DiamondUser就是具体状态了。它们都实现了抽象状态角色定义的接口。
l 为User转化UserLevel的操作是在各个具体状态中进行的。在这里可以看到这种状态的转化是有序列的,这样也只会有前后两个状态产生依赖。假设现在的会员系统中是没有钻石用户的,那么GoldUser的StateCheck()方法中应该是没有什么代码的,即使以后再要加DiamondUser类,我们也只需要修改GoldUser的SateCheck()方法,以根据一定的规则来为环境转化状态。
l 在这里,我们在环境中调用了StateCheck方法,在实际应用中,你可以根据需要在抽象状态中引入模版方法,对外公开这个模版方法,并且在模版方法中调用行为方法和转化状态的方法,当然,具体的行为还是由具体状态来实现的。
何时采用
l 从代码角度来说,如果一个类有多种状态,并且在类内部通过的条件语句判断的类状态来实现不同行为时候可以把这些行为单独封装为状态类。
l 从应用角度来说,如果一个对象有多种状态,如果希望把对象状态的转化以及由不同状态产生的行为交给具体的状态类去做,那么可以考虑状态模式。
实现要点
l 在环境角色中拥有状态角色的实例。
l 在状态角色中拥有环境角色的实例用于在具体状态中修改环境角色的状态。
l 状态对象之间的依赖可以通过加载外部配置的转化规则表等方法来消除。
l 状态模式和策略模式的主要区别是,前者的行为实现方式是由条件决定的,并且应当能不在客户端干预的情况下自己迁移到合适的状态,而后者的行为实现方式是由客户端选择的,并且能随时替换。
注意事项
l 过多的状态对象可能会增加系统负担,可以考虑把各种状态角色实现为无状态对象的享元,需要保存的额外状态由环境角色进行统一管理和处理。