适用性:在下面的两情况下均可以使用State模式:
l 一个对象的行为取决于它的状态,并且必须在运行时刻根据状态改变它的行为。
l 一个操作中含有庞大的多分支的条件豫剧,并且这些分支依赖于该对象的状态,这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构,State模式将每一个条件分支放入一个单独的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
参与者:
l Context(环境,Person)定义客户感兴趣的类。
l State(Moodstate):定义一个接口以封装与Context的一个特定状态相关的行为
l ConcreteState Subclasses(具体状态子类,如Angry)每一个子类实现一个与Context的状态相关的行为。
他们的协作关系是:
l Context将于状态相关的请求委托给当前的ConcreteState对象处理。
l Context可将自身作为一个参数传递给处理该请求的状态对象,这使得状态对象在必要的时候可访问Context。
l Context是客户使用的主要接口,客户可用状态对象来配置一个Context,一旦一个Context配置完毕,他的客户不再需要直接与状态对象打交道。
l Context或者ConcreteState子类都可以决定哪个状态是另外那个状态的后继者,以及是在何种条件下进行状态转换。
相应的代码:
MoodState代码:
package state;
public interface MoodState{
public void doSomething();
public void changeState();
}
Angry代码:
package state;
public class
implements MoodState{
Person p;
public Angry(Person p){
this.p = p;
}
public void doSomething(){
System.out.println("I'm angry!");
}
public void changeState(){
p.setState(new Happy(p));
}
}
Happy代码:
package state;
public class Happy implements MoodState{
Person p;
public Happy(Person p){
this.p = p;
}
public void doSomething(){
System.out.println("I'm happy!");
}
public void changeState(){
p.setState(new Mad(p));
}
}
Mad代码:
package state;
public class Mad implements MoodState{
Person p;
public Mad(Person p){
this.p=p;
}
public void doSomething(){
System.out.println("I'm Mad");
}
public void changeState(){
p.setState( new Angry(p));
}
}
Person代码:
package state;
public class Person{
private MoodState state;
public Person(){
state = new Mad(this);
}
public void setState(MoodState state){
this.state = state;
}
public void doSomething(){
state.doSomething();
state.changeState();
}
}
Client代码:
package state;
public class Client{
public static void main(String[] args){
Person p = new Person();
for(int i=0;i<10;i++)
p.doSomething();
}
}
总结:状态模式将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,使得状态转换显式化并且可以被共享。