一、 状态(State)模式的结构
状态模式允许一个对象在其内部状态改变的时候改变其行为。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为随之改变。
结构如下图所示:
通过使用多态性原则,可以动态地改变环境类Context的属性State的内容,使其从指向一个具体状态类变换到指向另一个具体状态类,从而使环境类的行为sampleOperation()由不同的具体状态类来执行。代码如下:
//Context类
public class Context{
private State state;
public void sampleOperation(){
state.sampleOperation();
}
//要有一个改变State对象的方法
public void setState(State state){
this.state = state;
}
}
//State接口
public interface State{
void sampleOperation();
}
//ConcreteState类
public class ConcreteState implement State{
public void sampleOperation(){}
}
状态模式的效果:
(1)、状态模式需要对每一个系统可能取得的状态创立一个状态类(State)的子类。当系统的状态变化时,系统便改变所选的子类。所有与一个特定的状态有关的行为都被包装到一个特定的对象里面,使得行为的定义局域化。因为同样的原因,如果有新的状态以及它对应的行为需要定义时,可以很方便地通过设立新的子类的方式回到系统里,不需要改动其他的子类。
(2)、由于每一个状态都包装到了类里面,就可以不必采用过程性的处理方式,使用长篇累牍的条件转移名。
(3)、使用状态模式使系统状态的变化变得很明显。由于不用一些属性(内部变量)来指明系统所处的状态,因此就不用担心修改这些属性不当而造成的错误。
(4)、可以在系统的不同部分使用相同的一些状态类的对象。这种共享对象的办法是与享元模式相符合的。事实上,此时这些状态对象基本上是只有行为而没有内部状态的享元模式。
(5)、状态模式的缺点是会造成大量的小的状态类:优点是使程序免于大量的条件转移语句,使程序实际上更易于维护。
(6)、系统所选的状态子类均是从一个抽象状态类或接口继承而来,Java语言的特性使得在java语言中使用状态模式较为安全。多态性原则是状态模式的核心。
二、 在什么情况下使用状态模式
(1)、一个对象的行为依赖于它所处的状态,对象的行为必须随着其状态的改变而改变。
(2)、对象的某个方法依赖于一重或多重的条件转移语句,其中大量的代码。状态模式把条件转移语句的每一个分支都包装到一个单独的类里。这使得这些条件转移分支能够以类的方式独立存在和演化。
三、 状态模式与策略模式的区别
状态模式与策略模式经常混淆。他们的简略类图都如下:
一个简单的方法便是考察环境角色是否有明显的状态和状态的过渡。如果环境角色只有一个状态,那么就应当使用策略模式。策略模式的特点是:一旦环境角色选择一个具体策略类,那么在整个环境类的生命周期里它都不会改变这个具体策略类。另一个微妙的区别在于,策略模式的环境类自己选择一个具体策略类;而状态模式的环境类是被外在原因放进一个具体状态中。策略模式所选的策略往往并不明显地告诉客户端它所选择的具体策略;而状态模式则相反,在状态模式里面,环境角色所处的状态是明显告诉客户端的。