状态模式
一意图
一些对象具有多种状态,而且在不同的状态下也具有不同的行为,这些状态在某些情况下又能够相互转换。
为了在编码时,对上述的对象能够好的进行设计和管理,我们可以使用一种被称之为状态模式的设计模式。
状态模式主要是解决当控制一个对象状态转换的条件表达式,过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列的类当中,这样就可以把复杂的判断逻辑简化。
二定义
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。状态模式是一种对象行为型模式。
三类图
Context(环境类):环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象。
State(抽象状态类):它用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态对应的方法,而在其子类中实现类这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。
ConcreteState(具体状态类):它是抽象状态类的子类,每一个子类实现一个与环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同。
四代码示例
自然界中的水,在常温状态下(如:27摄氏度)是液态的。当温度低于0摄氏度时,它会结冰凝固成固态。当温度大于100摄氏度时,它会蒸发成水蒸气,变成气态。
环境类:
public class Water {
private WaterState state; //维持一个对抽象状态对象的引用
private float temperature = 27;
public Water(){
this.state = new LiquidState(this);
}
//设置状态对象
public void setState(WaterState state) {
this.state = state;
}
//获取状态对象
public WaterState getState() {
return this.state;
}
//设置温度
public void setTemperature(float temperature){
this.temperature = temperature;
}
//获取温度
public float getTemperature(){
return temperature;
}
//升高温度
public void increaseTemperature(float changeTemperature){
String info = "Current water state is: "+state.stateName+",Water temperature is: "+temperature +". Increase temperature " + changeTemperature;
System.out.println(info);
state.increaseTemperature(changeTemperature);
state.showWaterInfo();
}
//降低温度
public void reduceTemperature(float changeTemperature){
String info = "Current water state is: "+state.stateName+",Water temperature is: "+temperature +". Reduce temperature " + changeTemperature;
System.out.println(info);
state.reduceTemperature(changeTemperature);
state.showWaterInfo();
}
}
抽象状态类
public abstract class WaterState {
protected Water water;
protected String stateName;
public abstract void increaseTemperature(float changeTemperature);
public abstract void reduceTemperature(float changeTemperature);
public void showWaterInfo() {
String info = "Water state is: "+stateName+",Water Temperature is: "+water.getTemperature()+" !";
System.out.println(info);
}
}
液态:具体状态类
public class LiquidState extends WaterState {
public LiquidState(Water water) {
this.water = water;
this.stateName = "Liquid";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
if(temperature > 100){
water.setState(new GasState (water));
}
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
if(temperature < 0){
water.setState(new SolidState (water));
}
}
}
固态:具体状态类
public class SolidState extends WaterState{
public SolidState(Water water) {
this.water = water;
this.stateName = "Solid";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
if(temperature > 0){
water.setState(new LiquidState (water));
}
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
}
}
气态:具体状态类
public class GasState extends WaterState {
public GasState(Water water) {
this.water = water;
this.stateName = "Gas";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
if(temperature < 100){
this.water.setState(new LiquidState(this.water));
}
else if(temperature < 0){
this.water.setState(new LiquidState(this.water));
}
}
}
测试
public class Test {
public static void main(String args[]) {
Water water = new Water();
water.increaseTemperature(80);
water.increaseTemperature(20);
water.reduceTemperature(60);
water.reduceTemperature(30);
water.reduceTemperature(50);
water.reduceTemperature(60);
}
}
运行结果:
Current water state is: Liquid,Water temperature is: 27.0. Increase temperature 80.0
Water state is: Gas,Water Temperature is: 107.0 !
Current water state is: Gas,Water temperature is: 107.0. Increase temperature 20.0
Water state is: Gas,Water Temperature is: 127.0 !
Current water state is: Gas,Water temperature is: 127.0. Reduce temperature 60.0
Water state is: Liquid,Water Temperature is: 67.0 !
Current water state is: Liquid,Water temperature is: 67.0. Reduce temperature 30.0
Water state is: Liquid,Water Temperature is: 37.0 !
Current water state is: Liquid,Water temperature is: 37.0. Reduce temperature 50.0
Water state is: Solid,Water Temperature is: -13.0 !
Current water state is: Solid,Water temperature is: -13.0. Reduce temperature 60.0
Water state is: Solid,Water Temperature is: -73.0 !
五总结
状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为。
当具体业务中出现新的状态的时候,只需要增加新定义的状态state子类,而对状态业务逻辑代码的修改相对较少,友好的支持了“开闭原则”。
状态模式可以消除庞大的条件分支语句,使得代码结构变得简单清晰,便于修改和扩展。
状态模式通过把各个状态的业务逻辑转移到state子类中,降低了程序的耦合性。