定义
对有状态的对象,把复杂的“逻辑判断”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
结构
状态模式包含以下主要角色。
- 环境角色(Context):也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
- 抽象状态角色(State):定义一个接口,用以封装环境对象中的特定状态所对应的行为。
- 具体状态角色(Concrete State):实现抽象状态所对应的行为。
案例
电梯运行系统,电梯有四种状态:开门、关门、停止、运行。运行的时候不能开门,开门的时候也不能运行等。
抽象状态类
package com.hupp.state;
/**
* 抽象状态类
*/
public abstract class LiftState {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//电梯开启
public abstract void open();
//电梯关闭
public abstract void close();
//电梯运行
public abstract void run();
//电梯停止
public abstract void stop();
}
环境类
package com.hupp.state;
/**
* 环境角色
*/
public class Context {
private LiftState liftState;
//设置当前状态对象
public void setLiftState(LiftState liftState) {
this.liftState = liftState;
this.liftState.setContext(this);
}
public void open() {
this.liftState.open();
}
public void close() {
this.liftState.close();
}
public void run() {
this.liftState.run();
}
public void stop() {
this.liftState.stop();
}
}
电梯四个状态类
package com.hupp.state;
public class ClosingState extends LiftState{
private final static ClosingState CLOSING_STATE = new ClosingState();
private ClosingState(){
}
public static ClosingState getInstance(){
return CLOSING_STATE;
}
@Override
public void open() {
super.context.setLiftState(OpeningState.getInstance());
super.context.open();
}
@Override
public void close() {
System.out.println("电梯关闭");
}
@Override
public void run() {
super.context.setLiftState(RunningState.getInstance());
super.context.run();
}
@Override
public void stop() {
super.context.setLiftState(StoppingState.getInstance());
super.context.stop();
}
}
package com.hupp.state;
public class OpeningState extends LiftState{
private final static OpeningState OPENING_STATE = new OpeningState();
private OpeningState(){
}
public static OpeningState getInstance(){
return OPENING_STATE;
}
//当前状态要执行的方法
@Override
public void open() {
System.out.println("电梯开启");
}
@Override
public void close() {
super.context.setLiftState(ClosingState.getInstance());
super.context.close();
}
@Override
public void run() {
//开启状态不能运行
}
@Override
public void stop() {
//开启状态,本身就是停止的
}
}
package com.hupp.state;
public class RunningState extends LiftState {
private final static RunningState RUNNING_STATE = new RunningState();
private RunningState() {
}
public static RunningState getInstance() {
return RUNNING_STATE;
}
@Override
public void open() {
}
@Override
public void close() {
}
@Override
public void run() {
System.out.println("电梯运行");
}
@Override
public void stop() {
super.context.setLiftState(StoppingState.getInstance());
super.context.stop();
}
}
package com.hupp.state;
public class StoppingState extends LiftState{
private final static StoppingState STOPPING_STATE = new StoppingState();
private StoppingState(){
}
public static StoppingState getInstance(){
return STOPPING_STATE;
}
@Override
public void open() {
super.context.setLiftState(OpeningState.getInstance());
super.context.open();
}
@Override
public void close() {
super.context.setLiftState(ClosingState.getInstance());
super.context.close();
}
@Override
public void run() {
super.context.setLiftState(RunningState.getInstance());
super.context.run();
}
@Override
public void stop() {
System.out.println("电梯停止");
}
}
客户端类
package com.hupp.state;
public class Client {
public static void main(String[] args) {
Context context = new Context();
context.setLiftState(OpeningState.getInstance());
context.run();
context.open();
context.close();
context.stop();
}
}
优缺点
- 优点
- 可以方便的管理状态、新增状态
- 允许状态转换逻辑与状态对象合成一体,而不用复杂的条件语句块
- 缺点
- 会增加系统类和对象的个数
- 结构和实现比较复杂,如果使用不当会导致程序结构和代码的混乱
- 对“开闭原则”的支持不太友好,新增状态的话可能还需要改变其他状态里的语句,比如上述例子中增加了一个维修状态,那么其他状态也要加上维修方法。