佛山网站设计资讯seo常用工具包括
行为设计模式之State(状态)设计模式
摘要:
本文介绍了行为设计模式中的State(状态)模式。该模式允许对象在内部状态改变时改变行为,解决对象行为依赖于状态的多分支条件判断问题。文章展示了状态模式的结构、适用场景以及一个售货机状态转换的代码示例。典型应用场景包括对象行为随状态显著变化、需避免大量条件分支、状态转换规则明确且可能变化、状态数量较多或可能增加等情况。常见应用领域涵盖游戏开发、用户界面、工作流引擎、网络协议和嵌入式系统等。状态模式通过将状态和行为封装到独立类中,提高了代码的可读性、可维护性和扩展性,符合开闭原则。
1)意图
允许一个对象在内部状态改变时改变它的行为。对象看起来似乎改变它的类。
2)结构
3)适用性
State 模式适用于:
- 一个对象的行为决定它的状态,并且它必须运行时刻根据改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。
/*** @author psd 行为设计模式之状态设计模式*/
public class StatePattern {public static void main(String[] args) {Context context = new Context();System.out.println("状态是:" + context.getState() + " 数量" + context.getResidueCount());// 购买成功 count = 2context.request();// 购买成功 count = 1context.request();// 购买成功 count = 0context.request();System.out.println("状态是:" + context.getState() + " 数量" + context.getResidueCount());// 无货,等待补货 count = 5context.request();System.out.println("状态是:" + context.getState() + " 数量" + context.getResidueCount());context.request();System.out.println("状态是:" + context.getState() + " 数量" + context.getResidueCount());}
}/*** 售卖机*/
class Context{private int residueCount;private State state;public int getResidueCount() {return residueCount;}public void setResidueCount(int residueCount) {this.residueCount = residueCount;}public State getState() {return state;}public void setState(State state) {this.state = state;}public void request(){state.handler(this);}public Context() {this.state = new StateA();this.residueCount = 3;}
}interface State{void handler(Context context);
}/*** 售货机状态A 有货*/
class StateA implements State{@Overridepublic void handler(Context context) {int residueCount = context.getResidueCount();if (residueCount >= 1){System.out.println("商品购买成功........");context.setResidueCount(residueCount - 1);if (0 == context.getResidueCount()){context.setState(new StateB());}}else {System.out.println("购买失败......");}}
}class StateB implements State{@Overridepublic void handler(Context context) {int residueCount = context.getResidueCount();if (0 == residueCount){System.out.println("商品购买失败....商品待补货");context.setResidueCount(5);System.out.println("补货成功,请重新购买");context.setState(new StateA());}}
}
4)以下是状态设计模式的典型使用场景:
1、对象拥有多个状态,且行为随状态显著变化:
这是最核心的场景。当一个对象的行为(方法执行的操作)会因其当前所处的状态(内部数据值)不同而发生根本性改变时。
例子:
电梯系统: 电梯有开门、关门、运行中、停止、故障等状态。按下楼层按钮这个行为,在开门状态下可能无效或需要等待关门,在运行中状态下会将目标楼层加入队列,在停止状态下会启动运行。
网络连接: 连接有已连接、正在连接、已断开、超时等状态。发送数据在已连接状态下会发送,在已断开状态下会尝试重连或报错,在正在连接状态下会排队或拒绝。
订单系统: 订单有待支付、已支付、已发货、已收货、已完成、已取消、退款中等状态。取消订单在待支付状态下可以取消,在已发货状态下可能需要联系客服拦截,在已完成状态下则无法取消。
2、需要避免大量条件分支语句(if-else / switch-case):
当根据对象状态来决定行为的逻辑变得非常复杂,导致一个方法(如handleRequest())内部充斥着大量的条件判断语句时。这不仅代码臃肿、难以阅读和维护,而且增加新状态或修改状态转换逻辑非常容易出错。
状态模式的价值: 它将每个状态的行为封装到独立的状态类中。主对象(Context)只需持有当前状态对象的引用,并将请求委托给当前状态对象处理。这样,添加新状态只需添加新的状态类,修改状态行为只需修改对应的状态类,极大地简化了Context类的逻辑,符合开闭原则。
3、状态转换规则相对明确且可能发生变化:
状态之间的转换有明确的逻辑(例如,订单从待支付只能转换到已支付或已取消)。状态模式将状态转换逻辑也封装在状态类内部(或一个集中的地方),使得转换规则更清晰、更易于管理和修改。
如果业务规则变化导致状态转换逻辑需要调整,修改集中在相关的状态类中,而不是散落在庞大的条件语句里。
4、状态数量较多或可能增加:
当状态数量较多(比如超过 3-5 个)时,使用状态模式的优势会愈发明显。它将复杂的状态相关行为分散到多个较小的类中,提高了代码的可读性和可维护性。
当预期未来状态可能会增加时,状态模式提供了良好的扩展性。添加新状态只需要实现新的状态类,并在适当的转换点引入它,通常不需要修改现有的状态类(除非转换规则变化)或Context类的主要逻辑。
5、需要清晰地表示状态及其行为:
状态模式显式地将每个状态及其对应的行为定义为一个独立的类。这使得状态的概念在代码中变得非常清晰和具体,有助于开发者理解整个状态机的工作流程。文档性也更好。
常见应用领域举例:
游戏开发:
游戏角色状态(站立、行走、奔跑、跳跃、攻击、受伤、死亡)。每种状态下角色的动画、移动速度、碰撞检测、输入响应都不同。
NPC AI 状态(巡逻、追击、攻击、逃跑、闲置)。
游戏流程状态(主菜单、游戏中、暂停、游戏结束、加载中)。
用户界面 (UI) / 前端开发:
按钮状态(正常、悬停、按下、禁用),每种状态有不同的外观和点击响应。
复杂组件状态(如一个文件上传组件:等待选择文件、上传中、上传成功、上传失败、暂停)。
表单验证状态(初始、验证中、有效、无效)。
工作流引擎:
业务流程(如订单处理、请假审批、报销流程)涉及多个状态节点,每个节点有特定的操作和允许的流转方向。
网络协议实现:
TCP 连接管理(LISTEN, SYN_SENT, SYN_RECEIVED, ESTABLISHED, FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT, CLOSING, LAST_ACK, TIME_WAIT, CLOSED)。协议栈的行为在每个状态下都严格定义。
嵌入式系统/硬件控制:
设备状态机(如打印机:空闲、预热中、打印中、卡纸、缺墨、关机)。不同状态下对按钮操作或传感器信号的反应不同。
编译器/解释器:
词法分析器(扫描器)在解析不同词法单元(标识符、数字、字符串、运算符)时处于不同的状态。
喜欢我的文章记得点个在看,或者点赞,持续更新中ing…