状态模式
状态模式(State Pattern)属于行为模式。它主要用来解决对象在多个状态转换时,需要对外输出不同行为的问题。状态和行为是一一对应的,状态之间可以相互转换。当一个对象的内在状态发生改变时,允许改变其行为,这个对象看起来像是改变了类。
状态模式的三个角色
- State(抽象状态角色):定义一个接口,封装与
Context
的一个特定状态相关的行为。 - ConcreteState(具体状态角色):每一个子类实现一个与
Context
的一个特定状态相关的行为。 - Context(环境角色):用于维护
State
实例,这个实例定义当前的状态。
代码演示
演示一个简单电灯开关的例子,电灯有两种状态,一个是开启状态,一个是关闭状态。
Context:环境角色电灯
package cn.personalweb.state;
public class Context {
private State state;
public String getState() {
return state.toString();
}
public void setState(State state) {
this.state = state;
}
}
State:抽象的状态
package cn.personalweb.state;
public interface State {
public void handle(Context context);
}
LightOff:具体的关灯状态
handle
中将电灯的状态设置为关灯状态
package cn.personalweb.state;
public class LightOff implements State {
@Override
public void handle(Context context) {
context.setState(this);
System.out.println("关灯了...");
}
@Override
public String toString() {
return "关灯状态";
}
}
LightOn:具体的开灯状态
handle
中将电灯的状态设置为开灯状态
package cn.personalweb.state;
public class LightOn implements State{
@Override
public void handle(Context context) {
context.setState(this);
System.out.println("开灯了...");
}
@Override
public String toString() {
return "开灯状态";
}
}
Client:客户端
package cn.personalweb.state;
public class Client {
public static void main(String[] args) {
LightOff lightOff = new LightOff();
LightOn lightOn = new LightOn();
Context context = new Context();
// 开灯
lightOn.handle(context);
System.out.println(context.getState());
// 关灯
lightOff.handle(context);
System.out.println(context.getState());
}
}
输出结果
开灯了...
开灯状态
关灯了...
关灯状态
状态模式优缺点及应用场景
优点
-
代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
-
方便维护。将容易产生问题的 if-else 语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都 要判断当前是什么状态,不但会产出很多 if-else 语句,而且容易出错
-
符合“开闭原则”。容易增删状态
缺点
- 会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度
应用场景
当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式