前端状态模式优雅管理应用状态前言各位前端小伙伴不知道你们有没有遇到过这种情况应用状态越来越复杂状态之间的转换难以管理我曾经开发过一个订单管理系统订单状态有十几种状态转换逻辑写得一团糟。后来我引入了状态模式代码变得清晰优雅状态模式核心概念什么是状态模式状态模式是一种行为设计模式它允许对象在内部状态改变时改变其行为看起来好像修改了它的类。状态模式的优势封装状态转换逻辑将状态转换集中管理消除复杂的条件判断用多态替代switch-case提高代码可读性状态转换一目了然易于扩展添加新状态只需添加新类状态模式结构┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Context │ │ State │ │ ConcreteState │ │ (上下文对象) │ │ (状态接口) │ │ (具体状态) │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ 1. 持有状态引用 │ │ │───────────────────────│ │ │ │ │ │ │ 2. 定义状态方法 │ │ │───────────────────────│ │ │ │ │ │ │ │ 3. 实现具体行为 │ │ │────────────────────────│状态模式实战示例1订单状态管理// 状态接口 class OrderState { handle(order) { throw new Error(handle() must be implemented) } } // 具体状态 class PendingState extends OrderState { handle(order) { console.log(订单待支付) order.setState(new PaidState()) } } class PaidState extends OrderState { handle(order) { console.log(订单已支付) order.setState(new ShippedState()) } } class ShippedState extends OrderState { handle(order) { console.log(订单已发货) order.setState(new DeliveredState()) } } class DeliveredState extends OrderState { handle(order) { console.log(订单已完成) } } // 上下文对象 class Order { constructor() { this.state new PendingState() } setState(state) { this.state state } process() { this.state.handle(this) } } // 使用 const order new Order() order.process() // 订单待支付 order.process() // 订单已支付 order.process() // 订单已发货 order.process() // 订单已完成示例2表单状态管理class FormState { handle(form) {} } class EmptyState extends FormState { handle(form) { console.log(表单为空) form.canSubmit false } } class ValidState extends FormState { handle(form) { console.log(表单有效) form.canSubmit true } } class InvalidState extends FormState { handle(form) { console.log(表单无效) form.canSubmit false } } class Form { constructor() { this.state new EmptyState() this.canSubmit false this.fields {} } setState(state) { this.state state this.state.handle(this) } updateField(field, value) { this.fields[field] value this.validate() } validate() { const hasEmptyField Object.values(this.fields).some(v !v) const hasError this.checkErrors() if (hasEmptyField) { this.setState(new EmptyState()) } else if (hasError) { this.setState(new InvalidState()) } else { this.setState(new ValidState()) } } checkErrors() { // 验证逻辑 return false } }示例3UI组件状态管理class ComponentState { enter(component) {} exit(component) {} } class NormalState extends ComponentState { enter(component) { component.element.style.opacity 1 } exit(component) {} } class HoverState extends ComponentState { enter(component) { component.element.style.opacity 0.8 component.element.style.transform scale(1.05) } exit(component) { component.element.style.opacity 1 component.element.style.transform scale(1) } } class ActiveState extends ComponentState { enter(component) { component.element.style.transform scale(0.95) } exit(component) { component.element.style.transform scale(1) } } class ButtonComponent { constructor(element) { this.element element this.state new NormalState() this.attachEventListeners() } setState(state) { this.state.exit(this) this.state state this.state.enter(this) } attachEventListeners() { this.element.addEventListener(mouseenter, () { this.setState(new HoverState()) }) this.element.addEventListener(mouseleave, () { this.setState(new NormalState()) }) this.element.addEventListener(mousedown, () { this.setState(new ActiveState()) }) this.element.addEventListener(mouseup, () { this.setState(new NormalState()) }) } }状态模式在前端框架中的应用React中的状态模式import { useState, useCallback } from react function OrderTracker() { const [status, setStatus] useState(pending) const statusConfig { pending: { label: 待支付, color: yellow, next: () setStatus(paid) }, paid: { label: 已支付, color: blue, next: () setStatus(shipped) }, shipped: { label: 已发货, color: orange, next: () setStatus(delivered) }, delivered: { label: 已完成, color: green, next: null } } const currentConfig statusConfig[status] return ( div div style{{ color: currentConfig.color }} {currentConfig.label} /div {currentConfig.next ( button onClick{currentConfig.next} 下一步 /button )} /div ) }Vue中的状态模式import { reactive, computed } from vue const useOrderState () { const state reactive({ status: pending }) const statusMap { pending: { label: 待支付, color: yellow }, paid: { label: 已支付, color: blue }, shipped: { label: 已发货, color: orange }, delivered: { label: 已完成, color: green } } const currentStatus computed(() statusMap[state.status]) const nextStatus { pending: () state.status paid, paid: () state.status shipped, shipped: () state.status delivered, delivered: () {} } return { state, currentStatus, next: nextStatus[state.status] } }状态模式vs其他模式状态模式vs策略模式特性状态模式策略模式关注点状态转换算法替换状态关系有状态转换逻辑策略之间独立使用场景对象有多种状态需要多种算法状态模式vs有限状态机特性状态模式有限状态机实现方式面向对象状态表/图复杂度中低灵活性高中可视化难易状态模式最佳实践1. 使用状态枚举const STATUS { PENDING: pending, PAID: paid, SHIPPED: shipped, DELIVERED: delivered }2. 集中管理状态转换const transitions { [STATUS.PENDING]: STATUS.PAID, [STATUS.PAID]: STATUS.SHIPPED, [STATUS.SHIPPED]: STATUS.DELIVERED, [STATUS.DELIVERED]: null }3. 使用工厂模式创建状态class StateFactory { static create(stateName) { const states { pending: PendingState, paid: PaidState, shipped: ShippedState, delivered: DeliveredState } return new states[stateName]() } }状态模式常见问题问题1状态数量过多解决方案合并相似状态使用层次状态机使用状态表问题2状态转换复杂解决方案使用状态转换表使用有限状态机库可视化状态图问题3难以测试解决方案为每个状态编写测试使用mock对象测试状态转换路径总结状态模式是管理复杂状态的利器封装状态转换集中管理状态逻辑消除条件判断用多态替代switch-case提高可读性状态转换一目了然易于扩展添加新状态只需添加新类现在开始使用状态模式管理你的应用状态吧你的代码会感谢你的最后一句忠告不要过度使用状态模式简单状态用if-else更合适
前端状态模式:优雅管理应用状态
前端状态模式优雅管理应用状态前言各位前端小伙伴不知道你们有没有遇到过这种情况应用状态越来越复杂状态之间的转换难以管理我曾经开发过一个订单管理系统订单状态有十几种状态转换逻辑写得一团糟。后来我引入了状态模式代码变得清晰优雅状态模式核心概念什么是状态模式状态模式是一种行为设计模式它允许对象在内部状态改变时改变其行为看起来好像修改了它的类。状态模式的优势封装状态转换逻辑将状态转换集中管理消除复杂的条件判断用多态替代switch-case提高代码可读性状态转换一目了然易于扩展添加新状态只需添加新类状态模式结构┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Context │ │ State │ │ ConcreteState │ │ (上下文对象) │ │ (状态接口) │ │ (具体状态) │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ 1. 持有状态引用 │ │ │───────────────────────│ │ │ │ │ │ │ 2. 定义状态方法 │ │ │───────────────────────│ │ │ │ │ │ │ │ 3. 实现具体行为 │ │ │────────────────────────│状态模式实战示例1订单状态管理// 状态接口 class OrderState { handle(order) { throw new Error(handle() must be implemented) } } // 具体状态 class PendingState extends OrderState { handle(order) { console.log(订单待支付) order.setState(new PaidState()) } } class PaidState extends OrderState { handle(order) { console.log(订单已支付) order.setState(new ShippedState()) } } class ShippedState extends OrderState { handle(order) { console.log(订单已发货) order.setState(new DeliveredState()) } } class DeliveredState extends OrderState { handle(order) { console.log(订单已完成) } } // 上下文对象 class Order { constructor() { this.state new PendingState() } setState(state) { this.state state } process() { this.state.handle(this) } } // 使用 const order new Order() order.process() // 订单待支付 order.process() // 订单已支付 order.process() // 订单已发货 order.process() // 订单已完成示例2表单状态管理class FormState { handle(form) {} } class EmptyState extends FormState { handle(form) { console.log(表单为空) form.canSubmit false } } class ValidState extends FormState { handle(form) { console.log(表单有效) form.canSubmit true } } class InvalidState extends FormState { handle(form) { console.log(表单无效) form.canSubmit false } } class Form { constructor() { this.state new EmptyState() this.canSubmit false this.fields {} } setState(state) { this.state state this.state.handle(this) } updateField(field, value) { this.fields[field] value this.validate() } validate() { const hasEmptyField Object.values(this.fields).some(v !v) const hasError this.checkErrors() if (hasEmptyField) { this.setState(new EmptyState()) } else if (hasError) { this.setState(new InvalidState()) } else { this.setState(new ValidState()) } } checkErrors() { // 验证逻辑 return false } }示例3UI组件状态管理class ComponentState { enter(component) {} exit(component) {} } class NormalState extends ComponentState { enter(component) { component.element.style.opacity 1 } exit(component) {} } class HoverState extends ComponentState { enter(component) { component.element.style.opacity 0.8 component.element.style.transform scale(1.05) } exit(component) { component.element.style.opacity 1 component.element.style.transform scale(1) } } class ActiveState extends ComponentState { enter(component) { component.element.style.transform scale(0.95) } exit(component) { component.element.style.transform scale(1) } } class ButtonComponent { constructor(element) { this.element element this.state new NormalState() this.attachEventListeners() } setState(state) { this.state.exit(this) this.state state this.state.enter(this) } attachEventListeners() { this.element.addEventListener(mouseenter, () { this.setState(new HoverState()) }) this.element.addEventListener(mouseleave, () { this.setState(new NormalState()) }) this.element.addEventListener(mousedown, () { this.setState(new ActiveState()) }) this.element.addEventListener(mouseup, () { this.setState(new NormalState()) }) } }状态模式在前端框架中的应用React中的状态模式import { useState, useCallback } from react function OrderTracker() { const [status, setStatus] useState(pending) const statusConfig { pending: { label: 待支付, color: yellow, next: () setStatus(paid) }, paid: { label: 已支付, color: blue, next: () setStatus(shipped) }, shipped: { label: 已发货, color: orange, next: () setStatus(delivered) }, delivered: { label: 已完成, color: green, next: null } } const currentConfig statusConfig[status] return ( div div style{{ color: currentConfig.color }} {currentConfig.label} /div {currentConfig.next ( button onClick{currentConfig.next} 下一步 /button )} /div ) }Vue中的状态模式import { reactive, computed } from vue const useOrderState () { const state reactive({ status: pending }) const statusMap { pending: { label: 待支付, color: yellow }, paid: { label: 已支付, color: blue }, shipped: { label: 已发货, color: orange }, delivered: { label: 已完成, color: green } } const currentStatus computed(() statusMap[state.status]) const nextStatus { pending: () state.status paid, paid: () state.status shipped, shipped: () state.status delivered, delivered: () {} } return { state, currentStatus, next: nextStatus[state.status] } }状态模式vs其他模式状态模式vs策略模式特性状态模式策略模式关注点状态转换算法替换状态关系有状态转换逻辑策略之间独立使用场景对象有多种状态需要多种算法状态模式vs有限状态机特性状态模式有限状态机实现方式面向对象状态表/图复杂度中低灵活性高中可视化难易状态模式最佳实践1. 使用状态枚举const STATUS { PENDING: pending, PAID: paid, SHIPPED: shipped, DELIVERED: delivered }2. 集中管理状态转换const transitions { [STATUS.PENDING]: STATUS.PAID, [STATUS.PAID]: STATUS.SHIPPED, [STATUS.SHIPPED]: STATUS.DELIVERED, [STATUS.DELIVERED]: null }3. 使用工厂模式创建状态class StateFactory { static create(stateName) { const states { pending: PendingState, paid: PaidState, shipped: ShippedState, delivered: DeliveredState } return new states[stateName]() } }状态模式常见问题问题1状态数量过多解决方案合并相似状态使用层次状态机使用状态表问题2状态转换复杂解决方案使用状态转换表使用有限状态机库可视化状态图问题3难以测试解决方案为每个状态编写测试使用mock对象测试状态转换路径总结状态模式是管理复杂状态的利器封装状态转换集中管理状态逻辑消除条件判断用多态替代switch-case提高可读性状态转换一目了然易于扩展添加新状态只需添加新类现在开始使用状态模式管理你的应用状态吧你的代码会感谢你的最后一句忠告不要过度使用状态模式简单状态用if-else更合适