设计模式——状态模式

状态模式

定义

当一个对象内在的状态改变时,允许其改变行为,这个对象看似改变了其类

状态模式的核心是封装,状态的变更引起行为的变更,从外部看来就好像这个对象对应的类发生了变化一样。

优缺点、应用场景

优点

  1. 结构清晰。避免使用switch和if-else来处理每个状态转变到另一个状态的细节
  2. 遵循设计原则。很好地体现了开闭原则和单一职责原则,每个状态作为一个独立类,专注自己的责任。
  3. 封装性好。高层模型不需要了解子类的具体实现,只需要按照暴露出的流程使用即可。

缺点

  1. 子类会太多。对于一个事物来说,状态多就会导致类膨胀,并且不同状态对于事件都有不同的处理方法

应用场景

  1. 行为随状态的改变而改变
  2. 条件、分支判断语句的替代

代码模拟场景

使用电梯时的状态,包括:开门、关门、运行、停止。每种状态向其他状态转变的逻辑都不同。

开门(Open) 关门(Close) 运行(Run) 停止(Stop)
开门状态 × ×
关门状态
运行状态 × ×
停止状态

状态模式

UML图

设计模式——状态模式_第1张图片

状态的抽象和实现

/**
 * 抽象电梯状态
 */
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();

}

/**
 * 电梯开门状态
 */
public class OpenState extends LiftState {
	@Override
	public void open() {
		System.out.println("电梯开门...");
	}

	/**
	 * 开门的状态下可以关门
	 */
	@Override
	public void close() {
		// 状态修改
		super.context.setLiftState(Context.CLOSE_STATE);
		// 动作委托CloseState来执行
		super.context.getLiftState().close();
	}

	/**
	 * 不能运行
	 */
	@Override
	public void run() {
	}

	/**
	 * 不能停止
	 */
	@Override
	public void stop() {
	}
}

/**
 * 电梯关门状态
 */
public class CloseState extends LiftState {
	/**
	 * 关门的状态下可以开门
	 */
	@Override
	public void open() {
		super.context.setLiftState(Context.OPEN_STATE);
		super.context.getLiftState().open();
	}


	@Override
	public void close() {
		System.out.println("电梯关门...");
	}

	/**
	 * 门关闭了就可以运行
	 */
	@Override
	public void run() {
		super.context.setLiftState(Context.RUN_STATE);
		super.context.getLiftState().run();
	}

	/**
	 * 关着门不按楼层也可以,就停那了
	 */
	@Override
	public void stop() {
		super.context.setLiftState(Context.STOP_STATE);
		super.context.getLiftState().stop();
	}
}

/**
 * 电梯运行状态
 */
public class RunState extends LiftState {
	/**
	 * 运行中不能开门
	 */
	@Override
	public void open() {
	}

	/**
	 * 门已经关上了
	 */
	@Override
	public void close() {
	}

	@Override
	public void run() {
		System.out.println("电梯正在运行...");
	}

	/**
	 * 到楼层了可以停下
	 */
	@Override
	public void stop() {
		super.context.setLiftState(Context.CLOSE_STATE);
		super.context.getLiftState().stop();
	}
}

/**
 * 电梯关闭状态
 */
public class StopState extends LiftState {
	/**
	 * 停下可以开门
	 */
	@Override
	public void open() {
		super.context.setLiftState(Context.OPEN_STATE);
		super.context.getLiftState().open();
	}

	/**
	 * 停止可以关门
	 */
	@Override
	public void close() {
		super.context.setLiftState(Context.CLOSE_STATE);
		super.context.getLiftState().close();
	}

	/**
	 * 可以再运行起来
	 */
	@Override
	public void run() {
		super.context.setLiftState(Context.RUN_STATE);
		super.context.getLiftState().run();
	}

	@Override
	public void stop() {
		System.out.println("电梯停下了...");
	}
}

上下文对象

/**
 * 上下文对象
 */
public class Context {
	/**
	 * 定义当前电梯的状态
	 */
	private LiftState liftState;
	public static final LiftState OPEN_STATE = new OpenState();
	public static final LiftState CLOSE_STATE = new CloseState();
	public static final LiftState RUN_STATE = new RunState();
	public static final LiftState STOP_STATE = new StopState();

	public void open() {
		this.liftState.open();
	}

	public void close() {
		this.liftState.close();
	}

	public void run() {
		this.liftState.run();
	}

	public void stop() {
		this.liftState.stop();
	}

	public LiftState getLiftState() {
		return liftState;
	}

	public void setLiftState(LiftState liftState) {
		this.liftState = liftState;
		this.liftState.setContext(this);
	}
}

入口类

private static void statePattern() {
	Context context = new Context();
	// 定义电梯初始状态为关闭
	context.setLiftState(Context.CLOSE_STATE);
	context.open();
	context.close();
	context.run();
	context.stop();
}

结果

设计模式——状态模式_第2张图片

参考书籍

秦小波《设计模式之禅》

你可能感兴趣的:(设计模式,设计模式,状态模式,java)