设计模式——状态模式

文章介绍了状态模式的概念,强调了它在对象状态改变时允许行为变化的特点,以及结构清晰、遵循设计原则的优点。通过电梯的四种状态(开门、关门、运行、停止)为例,展示了如何用状态模式来处理状态转换,避免了大量的条件判断。同时,指出了状态模式可能导致子类过多的缺点,并提供了相应的代码示例来说明如何实现这种模式。
摘要由CSDN通过智能技术生成

状态模式

定义

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

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

优缺点、应用场景

优点

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

缺点

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

应用场景

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

代码模拟场景

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

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

状态模式

UML图

在这里插入图片描述

状态的抽象和实现

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

结果

在这里插入图片描述

参考书籍

秦小波《设计模式之禅》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加把劲骑士RideOn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值