状态模式
在某些情况下,一些对象存在着比较多的状态,在不同的状态下,执行不同的方法,通常的解决办法就是为每个状态编写一个if…条件进行判断。当状态比较多,并且行为复杂的时候,会导致代码的可维护性、灵活性、扩展性降低,并且在增加新的状态的时候,代码也要随之修改,违背了开闭原则。
状态模式被设计来解决系统中复杂对象的状态变化以及不同状态下行为的封装问题。当系统中的某个对象存在多种状态,并且这些状态之间可以相互转化,不同的状态下的行为不相同时,可以考虑使用状态模式。
状态模式是将复杂对象的每个状态(准确的说是每个状态下的行为)从对象中分离出来,封装到专门的状态类中,使得对象接收状态,并且灵活转变状态和状态下的行为。
定义
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
结构
- Context(环境类):又称上下文类,是具有多种状态的复杂对象,其内部存在着多种状态并且各个状态下的行为不同。环境类中封装了一个抽象状态类对象,接收抽象状态类的实现类。
- State(抽象状态类):用于定义一个接口,内部定义了可执行的方法,其子类实现这个方法以完成在不同状态下的独特行为。State类与环境类产生关联。
- ConcreteState(具体状态类):抽象状态类的子类。每一个具体状态类代表着复杂对象的一种具体状态,内部封装了这个状态下的独特行为。
实例
package state;
public class People {
private PhysicalState state;
public void setPhysicalState(PhysicalState state) {
this.state = state;
}
public void action() {
state.action();
}
}
package state;
public interface PhysicalState {
public void action();
}
package state;
public class HealthyState implements PhysicalState {
@Override
public void action() {
System.out.println("起床干活");
}
}
package state;
public class TiredState implements PhysicalState {
@Override
public void action() {
System.out.println("太累了,休息");
}
}
package state;
public class Test {
public static void main(String[] args) {
People p = new People();
p.setPhysicalState(new HealthyState());
p.action();
}
}
几种更改对象状态的方法
- 在环境对象中设置状态转换的方法
- 设置枚举类,通过枚举类static方法根据参数返回相应的状态对象
- 设置基础状态类,由基础状态类设置状态
优点
- 状态模式将封装了状态转换规则,可以对状态转换规则进行集中管理,而不是分散在各个业务方法中
- 将不同状态下的业务规则进行了分离,使得维护和灵活性变强
- 语序状态转换逻辑和状态对象合成一体,而不是提供一个巨大的条件语句块
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数
缺点
- 状态模式会增加系统中对象的个数
- 状态模式的结构和实现都较为复杂,使用不当会导致结构和代码混乱
- 并不能完全符合开闭原则,必须有负责转换状态的语句
适用场景
- 对象的行为非常依赖于对象的状态,随着状态的改变发生变化
- 代码中包含大量的if…else有关状态判断的语句,对这些语句进行简化