状态模式用于解决对象的状态转换以及不同状态下不同行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同(解释:对象的一些方法根据状态的不同会执行不同的逻辑,并且执行完后可能改变当前状态)时可以使用状态模式。状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用。
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
Context(环境类):环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态。环境类实际上是真正拥有状态的对象,我们只是将环境类中与状态有关的代码提取出来封装到专门的状态类中。
State(抽象状态类):它用于定义一个接口以封装与环境类的一个特定状态相关的行为。
解释:抽象状态类声明的方法是环境类中会因状态不同而有不同实现逻辑的方法, 可以是多个,因此这些方法的实现放在了具体状态类中,环境类中这些方法的发现只需要调用状态类相应的方法即可,调用过程中,根据不同的状态子类,会有不同的逻辑实现。
ConcreteState(具体状态类):每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态。
在状态模式的使用过程中,一个对象的状态之间还可以进行相互转换,通常有两种实现状态转换的方式:
(1) 统一由环境类来负责状态之间的转换,此时,环境类还充当了状态管理器(State Manager)角色,在环境类的业务方法中通过对某些属性值的判断实现状态转换,还可以提供一个专门的方法用于实现属性判断和状态转换。
(2) 由具体状态类来负责状态之间的转换,可以在具体状态类的业务方法中判断环境类的某些属性值再根据情况为环境类设置新的状态对象,实现状态转换,此时,状态类与环境类之间就将存在依赖或关联关系,因为状态类需要访问环境类中的属性值。
共享状态
如果希望在系统中实现多个环境对象共享一个或多个状态对象,或者多个对象状态保持一致,那么需要将这些状态对象定义为环境类的静态成员对象。
状态模式的主要优点如下:
(1) 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
(2) 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
(3) 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
(4) 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。