20.状态模式
2018-08-14 本文已影响0人
0x70e8
[TOC]
状态模式
状态模式是使用类来表示一种状态,和通常使用类来表示一个实体不同,这种应用场景下表示的是一个非实体。
一般而言,一个实体的状态能够影响实体上的行为,如一个人睡着了就不能工作,一个实体的行为反过来又会影响他的状态,工作了就从睡着变成醒来的状态。
类是有行为的数据,在类里面定义状态可能发生的行为(方法),然后在行为(方法)内判断行为能否发生,并决定是否会影响当前的状态。
此模式能将代码逻辑从大量的if-else中解脱出来,分散到多个类中。
示例
如电梯的上下开关和其状态的关系。
不使用state模式的伪代码
// 电梯的状态 开着门open、关着门close、运行中running、静止stop
// 传入电梯动作(开门open、关门close、运行run、停止stop)
void act(action){
if(action is run){
//判断当前状态
if(curState is run){
}else if(curState is stop){
}else if(cur is close){
}else{
// open
}
}else if(action is stop){
//判断当前状态
if(curState is run){
}else if(curState is stop){
}else if(cur is close){
}else{
// open
}
}else if(action is open the door){
//判断当前状态
if(curState is run){
}else if(curState is stop){
}else if(cur is close){
}else{
// open
}
}else{//action is close the door
//判断当前状态
if(curState is run){
}else if(curState is stop){
}else if(cur is close){
}else{
// open
}
}
}
发现会有大量的if-else语句,且在内部还需要针对action来修改电梯的状态,逻辑很复杂,并且当状态或者行为有新增的时候,将是一场噩梦。
使用state模式
使用类表示状态,实际上是封装状态和行为:
- 状态接口和状态的表示
public abstract class LiftState {
private StateEnum state;
public abstract void run();
public abstract void stop();
public abstract void close();
public abstract void open();
/**
* @return the state
*/
public StateEnum getState() {
return state;
}
/**
* @param state
* the state to set
*/
public void setState(StateEnum state) {
this.state = state;
}
}
public enum StateEnum {
RUN, STOP, OPEN, CLOSE;
}
- 具体状态类
public class LIftCloseState extends LiftState {
public LIftCloseState() {
this.setState(StateEnum.CLOSE);
}
@Override
public void run() {
System.out.println("run it!");
this.setState(StateEnum.RUN);
}
@Override
public void stop() {
System.out.println("stop it");
this.setState(StateEnum.STOP);
}
@Override
public void close() {
System.out.println("already closed ");
this.setState(StateEnum.CLOSE);
}
@Override
public void open() {
System.out.println("open it");
this.setState(StateEnum.OPEN);
}
}
public class LIftOpenState extends LiftState {
public LIftOpenState() {
this.setState(StateEnum.OPEN);
}
@Override
public void run() {
System.out.println("cannot run!");
}
@Override
public void stop() {
System.out.println("already stop");
this.setState(StateEnum.STOP);
}
@Override
public void close() {
System.out.println("close it");
this.setState(StateEnum.CLOSE);
}
@Override
public void open() {
System.out.println("already open");
this.setState(StateEnum.OPEN);
}
}
public class LIftRunState extends LiftState {
public LIftRunState() {
this.setState(StateEnum.RUN);
}
@Override
public void run() {
System.out.println("already run!");
this.setState(StateEnum.RUN);
}
@Override
public void stop() {
System.out.println("stop it");
this.setState(StateEnum.STOP);
}
@Override
public void close() {
System.out.println("already closed");
this.setState(StateEnum.CLOSE);
}
@Override
public void open() {
System.out.println("can not open");
}
}
public class LIftStopState extends LiftState {
public LIftStopState() {
this.setState(StateEnum.STOP);
}
@Override
public void run() {
System.out.println("start run!");
this.setState(StateEnum.RUN);
}
@Override
public void stop() {
System.out.println("already stop");
this.setState(StateEnum.STOP);
}
@Override
public void close() {
System.out.println("close the lift");
this.setState(StateEnum.CLOSE);
}
@Override
public void open() {
System.out.println("open the lift");
this.setState(StateEnum.OPEN);
}
}
- Client
public class Client {
public static void main(String[] args) {
LiftState state = new LIftOpenState();
state.close();
state.run();
state.stop();
state.open();
state.close();
state.run();
state.open();
state.stop();
}
}
可以发现,状态的判断分散到状态的类中去了,每个状态类维护其上可以发生的行为以及行为会改变的状态。没有了if-else语句,且此情况下,增加一个状态时只需要增加一个类,可能需要修改其他state的方法(影响状态的行为),但是维护起来比if-else方便很多。
缺点是会产生很多类。