当前位置: 首页 > news >正文

状态模式

状态模式:封装状态变化的行为设计艺术

一、状态模式的定义与核心思想

状态模式(State Pattern) 是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其核心思想是 “将对象的状态封装为独立的状态类,将状态转换逻辑与状态对应的行为分离”—— 通过将不同状态下的行为封装到具体状态类中,让上下文对象(持有状态的对象)在状态变化时,自动切换对应的行为,无需在上下文类中编写大量条件判断语句。

简单来说,状态模式解决了 “对象因状态变化导致行为切换,进而产生大量条件判断” 的问题。例如,电梯的运行状态(停止、上升、下降)、订单的生命周期(待支付、已支付、已发货、已完成)、播放器的状态(播放、暂停、停止)等场景,都适合用状态模式封装状态变化与对应行为。

二、状态模式的角色构成

状态模式通常包含以下 3 个核心角色,各角色职责明确、协作完成状态切换与行为执行:

角色名称 核心职责 示例(电梯运行场景)
上下文(Context) 持有当前状态对象,提供状态切换的接口,对外暴露统一的行为方法(委托给当前状态对象执行) Elevator 类(电梯)
抽象状态(State) 定义所有具体状态的公共接口,声明状态对应的行为方法(如电梯的开门、关门、运行方法) ElevatorState 接口
具体状态(ConcreteState) 实现抽象状态接口,封装该状态下的具体行为,同时可包含状态转换的逻辑(如从 “停止” 状态切换到 “上升” 状态) StoppedState(停止状态)、RunningUpState(上升状态)、RunningDownState(下降状态)

三、状态模式的工作原理与实现

1. 工作流程

  1. 上下文对象初始化时,设置初始状态(如电梯初始状态为 “停止”);

  2. 客户端调用上下文的行为方法(如电梯的 “上升” 方法);

  3. 上下文对象将行为委托给当前持有的状态对象执行;

  4. 具体状态对象执行对应行为,若行为触发状态变化(如电梯从 “停止” 变为 “上升”),则由状态对象通知上下文切换到新状态;

  5. 后续客户端调用上下文行为时,将委托给新的状态对象执行。

2. 基础实现(电梯运行状态管理)

以电梯的核心状态(停止、上升、下降)为例,实现状态模式,封装不同状态下的行为与状态转换:

(1)抽象状态(State)
// 抽象状态:电梯状态接口,定义电梯的核心行为public interface ElevatorState {void openDoor(); // 开门void closeDoor(); // 关门void runUp(); // 上升void runDown(); // 下降void stop(); // 停止}
(2)上下文(Context)
// 上下文:电梯类,持有当前状态,对外暴露统一行为接口public class Elevator {// 定义所有可能的状态(也可通过工厂模式创建,此处简化)public final ElevatorState STOPPED_STATE = new StoppedState(this);public final ElevatorState RUNNING_UP_STATE = new RunningUpState(this);public final ElevatorState RUNNING_DOWN_STATE = new RunningDownState(this);private ElevatorState currentState; // 当前状态// 初始化:电梯默认处于停止状态public Elevator() {this.currentState = STOPPED_STATE;System.out.println("电梯初始状态:停止");}// 状态切换方法:由具体状态对象调用,切换当前状态public void setState(ElevatorState state) {this.currentState = state;}// 对外暴露的行为方法:委托给当前状态执行public void openDoor() {currentState.openDoor();}public void closeDoor() {currentState.closeDoor();}public void runUp() {currentState.runUp();}public void runDown() {currentState.runDown();}public void stop() {currentState.stop();}}
(3)具体状态(ConcreteState)
① 停止状态(StoppedState)
// 具体状态:停止状态,实现停止状态下的行为与状态转换public class StoppedState implements ElevatorState {private Elevator elevator; // 持有上下文引用,用于切换状态public StoppedState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {// 停止状态下可开门System.out.println("电梯处于停止状态,开门成功~");}@Overridepublic void closeDoor() {// 停止状态下可关门(若已开门)System.out.println("电梯处于停止状态,关门成功~");}@Overridepublic void runUp() {// 停止状态下可切换为上升状态System.out.println("电梯从停止状态开始上升~");elevator.setState(elevator.RUNNING_UP_STATE); // 切换到上升状态}@Overridepublic void runDown() {// 停止状态下可切换为下降状态System.out.println("电梯从停止状态开始下降~");elevator.setState(elevator.RUNNING_DOWN_STATE); // 切换到下降状态}@Overridepublic void stop() {// 已处于停止状态,无需操作System.out.println("电梯已处于停止状态,无需重复停止~");}}
② 上升状态(RunningUpState)
// 具体状态:上升状态,实现上升状态下的行为与状态转换public class RunningUpState implements ElevatorState {private Elevator elevator;public RunningUpState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {// 上升状态下不可开门(安全限制)System.out.println("电梯正在上升,无法开门!");}@Overridepublic void closeDoor() {// 上升状态下门已关闭,无需操作System.out.println("电梯正在上升,门已关闭~");}@Overridepublic void runUp() {// 已处于上升状态,无需操作System.out.println("电梯正在上升,保持运行~");}@Overridepublic void runDown() {// 上升状态下不可直接切换为下降状态(需先停止)System.out.println("电梯正在上升,无法直接下降!请先停止~");}@Overridepublic void stop() {// 上升状态下可切换为停止状态System.out.println("电梯停止上升,切换为停止状态~");elevator.setState(elevator.STOPPED_STATE); // 切换到停止状态}}
③ 下降状态(RunningDownState)
// 具体状态:下降状态,实现下降状态下的行为与状态转换public class RunningDownState implements ElevatorState {private Elevator elevator;public RunningDownState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {// 下降状态下不可开门(安全限制)System.out.println("电梯正在下降,无法开门!");}@Overridepublic void closeDoor() {// 下降状态下门已关闭,无需操作System.out.println("电梯正在下降,门已关闭~");}@Overridepublic void runUp() {// 下降状态下不可直接切换为上升状态(需先停止)System.out.println("电梯正在下降,无法直接上升!请先停止~");}@Overridepublic void runDown() {// 已处于下降状态,无需操作System.out.println("电梯正在下降,保持运行~");}@Overridepublic void stop() {// 下降状态下可切换为停止状态System.out.println("电梯停止下降,切换为停止状态~");elevator.setState(elevator.STOPPED_STATE); // 切换到停止状态}}
(4)客户端测试
public class Client {public static void main(String[] args) {// 创建上下文对象(电梯)Elevator elevator = new Elevator();System.out.println("n1. 测试停止状态下的操作:");elevator.openDoor(); // 停止状态可开门elevator.closeDoor(); // 停止状态可关门elevator.runUp(); // 停止状态切换为上升System.out.println("n2. 测试上升状态下的操作:");elevator.openDoor(); // 上升状态不可开门elevator.runUp(); // 上升状态保持运行elevator.stop(); // 上升状态切换为停止System.out.println("n3. 测试停止状态切换为下降:");elevator.runDown(); // 停止状态切换为下降System.out.println("n4. 测试下降状态下的操作:");elevator.runUp(); // 下降状态不可直接上升elevator.stop(); // 下降状态切换为停止}}
输出结果
电梯初始状态:停止1. 测试停止状态下的操作:电梯处于停止状态,开门成功~电梯处于停止状态,关门成功~电梯从停止状态开始上升~2. 测试上升状态下的操作:电梯正在上升,无法开门!电梯正在上升,保持运行~电梯停止上升,切换为停止状态~3. 测试停止状态切换为下降:电梯从停止状态开始下降~4. 测试下降状态下的操作:电梯正在下降,无法直接上升!请先停止~电梯停止下降,切换为停止状态~

3. 扩展:状态模式的灵活扩展(新增 “故障状态”)

状态模式的核心优势是易于扩展新状态,无需修改原有状态类和上下文类,只需新增具体状态类并实现抽象状态接口:

(1)新增具体状态:故障状态(FaultState)
// 新增具体状态:故障状态public class FaultState implements ElevatorState {private Elevator elevator;public FaultState(Elevator elevator) {this.elevator = elevator;}@Overridepublic void openDoor() {// 故障状态下仅允许手动开门(紧急情况)System.out.println("电梯处于故障状态,紧急开门成功(仅手动操作)~");}@Overridepublic void closeDoor() {System.out.println("电梯处于故障状态,关门成功~");}@Overridepublic void runUp() {System.out.println("电梯处于故障状态,无法上升!");}@Overridepublic void runDown() {System.out.println("电梯处于故障状态,无法下降!");}@Overridepublic void stop() {// 故障状态下停止操作无效(已停止运行)System.out.println("电梯处于故障状态,已停止运行~");}}
(2)上下文扩展(添加故障状态)
public class Elevator {// 新增故障状态public final ElevatorState FAULT_STATE = new FaultState(this);// 其他代码不变...// 新增故障触发方法(对外暴露)public void triggerFault() {System.out.println("n触发电梯故障!");this.setState(FAULT_STATE);}}
(3)扩展客户端测试
public class Client {public static void main(String[] args) {Elevator elevator = new Elevator();System.out.println("n5. 测试故障状态:");elevator.triggerFault(); // 触发故障elevator.openDoor(); // 故障状态紧急开门elevator.runUp(); // 故障状态无法上升elevator.stop(); // 故障状态已停止}}
扩展输出结果
5. 测试故障状态:触发电梯故障!电梯处于故障状态,紧急开门成功(仅手动操作)~电梯处于故障状态,无法上升!电梯处于故障状态,已停止运行~

四、状态模式的应用场景

状态模式适用于以下场景:

  1. 对象行为随状态变化而变化:例如,订单状态(待支付→已支付→已发货→已完成),不同状态下的订单支持的操作(取消订单、退款、确认收货)不同。

  2. 避免大量条件判断语句:若上下文类中存在大量 if-elseswitch-case 语句判断状态并执行不同行为,适合用状态模式重构(将条件判断转换为状态类的多态调用)。

  3. 状态转换逻辑复杂:状态之间的转换规则较多,且转换逻辑与状态行为紧密相关(如电梯的状态转换受安全规则限制)。

  4. 需要动态切换状态:对象在运行时需根据外部事件动态切换状态,且切换后行为需自动调整(如播放器的播放 / 暂停 / 停止状态切换)。

五、状态模式的优缺点

优点

  1. 封装状态与行为:将不同状态下的行为封装到独立的状态类中,符合 “单一职责原则”,代码结构清晰。

  2. 消除条件判断:避免上下文类中大量的条件判断语句,通过状态类的多态调用实现行为切换,提高代码可维护性。

  3. 易于扩展新状态:新增状态只需实现抽象状态接口,无需修改原有代码,符合 “开闭原则”(如电梯新增故障状态无需改动原有状态类)。

  4. 状态转换逻辑清晰:状态转换规则集中在具体状态类中,便于理解和维护。

缺点

  1. 类数量增多:每个状态对应一个具体状态类,若状态数量较多(如订单有 10 种状态),会导致系统中类的数量激增,增加开发和维护成本。

  2. 状态类与上下文耦合:具体状态类持有上下文引用(用于切换状态),导致状态类与上下文存在一定耦合(可通过引入状态管理器降低耦合)。

  3. 简单状态场景冗余:若对象只有少数几种状态,且状态转换逻辑简单,使用状态模式会增加不必要的复杂性(直接用条件判断更简洁)。

六、状态模式与命令模式的核心区别

状态模式与命令模式均为行为型设计模式,且都通过封装实现解耦,但核心目标和应用场景差异显著:

维度 状态模式 命令模式
核心目标 封装状态变化与状态对应的行为 封装请求,解耦发送者与接收者
角色关系 上下文持有状态,状态依赖上下文(双向关联) 调用者持有命令,命令持有接收者(单向关联)
行为触发 行为由当前状态决定(状态驱动) 行为由命令对象决定(请求驱动)
状态 / 命令复用 状态可在多个上下文间复用 命令可在多个调用者间复用
典型场景 电梯状态、订单状态、播放器状态 遥控器操作、撤销 / 重做、命令队列

简单来说:状态模式是 “状态决定行为”,命令模式是 “请求触发行为”—— 状态模式聚焦对象自身的状态变化,命令模式聚焦请求的发送与执行分离。

http://www.jsqmd.com/news/69616/

相关文章:

  • 每日3题 4(咕咕咕
  • 基于事件驱动机制的提醒系统设计方案
  • docker快速上手
  • 全球首个液冷迷你机!abee AI Station 395 Max工作站图赏
  • Docker环境下Redis ACL实战踩坑记:权限、挂载与用户配置解析
  • 一例罗技M275鼠标空键程处理
  • Alientech KESS V3: Master Bench-Boot Protocols Activation for Agri Trucks Buses
  • 洛谷U640022 找割点 题解 点双连通分量
  • Alientech KESS V3 Master OBD Protocol Activation: Bike, ATV, UTV – Boost Repair Diagnostics
  • 命令模式
  • 第50天(中等题 数据结构)
  • C++多线程
  • Alientech KESS3 Master: Efficient OBD Protocols Activation for Agri Trucks Buses
  • 内网环境-centos7.6配置chrom和flask项目
  • selenium其他重要的Api
  • 机器学习基础
  • # sg.计算器
  • 洛谷P2860 [USACO06JAN] Redundant Paths G 题解 边双连通分量
  • AI真好玩系列-免费解锁 Google Gemini 的几种方式
  • 智能猫砂盆方案商权威推荐:技术驱动宠物养护新体验 - 星报
  • 网络线序问题了解
  • 洛谷U640024 找割边 题解
  • Python 学习笔记(01)
  • Python Flask service provide data list and retrieve and display in chrome via html and javascript
  • 2025最新PC仿石砖增强剂品牌TOP5评测!绿色建材赋能市政工程,权威榜单发布 - 全局中转站
  • 图文并茂-手把手教宝子们3分钟用 GitHub Pages 搭建免费网站 (保姆级教程)
  • 2025权威聚焦:智能门窗控制器解决方案商综合推荐,引领智慧生活新入口 - 星报
  • 2025最新聚脲防腐防水涂料/厂家TOP5评测!环保科技+工程实证权威榜单发布,功能涂料赋能基建防护新生态 - 全局中转站
  • 2025最新彩砖专用水性色浆服务商/厂家TOP5评测!环保创新+性能实证权威榜单发布,技术赋能重构彩砖涂装生态 - 全局中转站
  • 剪映vip破解版 分享