在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
简单来说:状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
一个对象的状态依赖于它的变量的取值情况,对象在不同的运行环境中,可能具有不同的状态。在许多情况下,对象调用方法所产生的行为效果依赖于它当时的状态。
状态模式的关键是将对象的状态封装成独立的类,对象(Context)调用方法时,可以委托当前对象所具有的状态(ConcreteState)调用相应的方法,使当前对象看起来好像修改了它的类。
1、行为随状态改变而改变的场景。
2、条件、分支语句的代替者。
3、一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。
状态模式包括三种角色。
环境(Context): 环境是一个类,该类含有抽象状态(State)声明的变量,可以引用任何具体状态类的实例。用户对该环境(Context)类的实例在某种状态下的行为感兴趣。
抽象状态(State): 抽象状态是一个接口或抽象类。抽象状态中定义了与环境(Context)的一个特定状态相关的若干个方法。
具体状态(ConcreteState): 具体状态是实现(扩展)抽象状态(抽象类)的类。
以下通过一个简单的问题来描述怎样使用状态模式,这个简单的问题就是:设计带文字提示信息的温度计。带文字提示细腻的温度计可以根据用户的需求显示某些提示信息,比如用户希望温度在0度以下,显示提示信息为“低温温度”,温度在10-26度至今时,显示提示信息为“正常温度”,当温度在大于39度时,显示提示信息为“高温温度”。
1.抽象状态(State)
对于本问题,抽象状态(State)是TemperatureState接口,代码如下所示:
里面只有一个showTemperature()方法,可以显示具体温度的状态。
public interface TemperatureState {
public void showTemperature();
}
2.具体状态(ConcreteState)
对于本问题,共有三个具体状态角色,分别是LowState,MiddleState和HeightState类,分别如下所示:
在里面定义一个默认的温度变量n,并实现了抽象状态的showTemperature()方法。
LowState.java
public class LowState implements TemperatureState{
double n=0;
public LowState(double n) {
if(n<0)
this.n = n;
}
@Override
public void showTemperature() {
System.out.println("现在的温度是"+n+"属于低温度");
}
}
MiddleState.java
public class MiddleState implements TemperatureState{
double n=15;
public MiddleState(double n) {
if(n>0 && n<26)
this.n = n;
}
@Override
public void showTemperature() {
System.out.println("现在的温度"+n+"属于正常温度");
}
}
HeightState.java
public class HeightState implements TemperatureState{
double n=30;
public HeightState(double n) {
if(n>=39)
this.n = n;
}
@Override
public void showTemperature() {
System.out.println("现在的温度"+n+"属于高温度");
}
}
3.环境(Context)
本问题中,环境角色是Thermometer类,代码如下:
在该类中有抽象状态的类变量引用,并通过set方法设置当前具体状态,通过showTemperature()方法显示当前类变量state的温度情况。
public class Thermometer {
TemperatureState state;
public void showMessage(){
System.out.println("********");
state.showTemperature();
System.out.println("********");
}
public void setState(TemperatureState state){
this.state=state;
}
}
4.测试程序
Application.java
public class Application {
public static void main(String[] args) {
TemperatureState state=new LowState(-12);
Thermometer thermometer=new Thermometer();//定义Context(上下文)
thermometer.setState(state);
thermometer.showMessage();
//切换状态
state=new MiddleState(20);
thermometer.setState(state);
thermometer.showMessage();
//切换状态
state=new HeightState(39);
thermometer.setState(state);
thermometer.showMessage();
}
}
1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
1.对状态进行建模时,状态迁移是一个核心内容;然而,在选择策略时,迁移与此毫无关系。另外,策略模式允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有;
2.策略模式用于随不同外部环境采取不同行为的场合;
3.在状态模式中,状态的迁移是由对象的内部条件决定,外界只关心起接口,不必关心其状态对象的创建与转化;而策略模式里,采取何种策略由外部条件决定。