状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,使对象看起来似乎修改了它的类。
状态模式的核心概念
环境类(Context):
持有当前状态对象,负责状态的切换,同时对外暴露统一的行为接口。
抽象状态类(State):
定义所有具体状态需要实现的接口或我者抽象类。
具体状态类(ConcreteState):
实现抽象状态定义的行为,每个具体状态类封装了对应的操作逻辑,并且可以
决定是否切换到其他状态。
代码示例
-
状态接口(State)
定义了所有具体状态类的公共接口,声明了一个
action()方法,用于表示该状态下的行为。javapublic interface State { void action(); } -
具体状态类
实现
State接口,每个类对应一种具体状态,并实现该状态下的action()方法(即该状态的具体行为):PendingState:订单待支付状态,行为是提示"等待用户支付";PaidState:订单已支付状态,行为是提示"请发货";ShippedState:订单已发货状态,行为是提示"等待接收";CompletedState:订单已完成状态,行为是提示"订单已完成"。
javapublic class PendingState implements State { @Override public void action() { System.out.println("订单待处理,等待用户支付。"); } } public class PaidState implements State { @Override public void action() { System.out.println("订单已支付,请发货。"); } } public class ShippedState implements State { @Override public void action() { System.out.println("订单已发货,请等待接收。"); } } public class CompletedState implements State { @Override public void action() { System.out.println("订单已完成。"); } } -
环境类(ContextState)
维护一个当前状态的引用(
state),并提供方法(setState())用于切换状态。通过request()方法委托当前状态的action()方法执行具体行为。javapublic class ContextState { private State state; // 当前状态 public void setState(State state) { // 切换状态 this.state = state; } public void request() { // 委托当前状态执行行为 state.action(); } } -
使用示例(StateTest)
通过环境类切换不同状态,并调用
request()触发对应状态的行为,体现了"状态改变时行为随之改变"的特点:javapublic class StateTest { public static void main(String[] args) { ContextState context = new ContextState(new PendingState()); context.request(); // 待支付状态的行为 context.setState(new PaiedState()); context.request(); // 已支付状态的行为 // 切换其他状态... } }
状态模式的核心思想
- 将对象的状态封装为独立的类,使状态的切换和行为的变化更加灵活,避免了大量
if-else或switch判断。 - 环境类(
ContextState)无需关心具体状态的实现,只需通过切换状态对象即可改变行为,符合"开放-封闭原则"。
状态模式的优点
优点
-
封装状态行为,职责清晰
每个状态(如
PendingState、PaiedState等)的行为被封装在独立的类中,符合"单一职责原则"。例如,CompletedState仅负责处理"订单已完成"状态的行为,避免了将所有状态逻辑混杂在一个类中。 -
消除大量条件判断
无需通过
if-else或switch判断当前状态再执行对应行为,而是通过切换状态对象(如context.setState(new PaiedState()))直接触发行为,代码更简洁、可读性更高。例如,订单状态切换时,ContextState只需调用request(),无需关心具体逻辑。 -
状态切换灵活,扩展性强
新增状态时,只需新增一个实现
State接口的具体类(如新增"退款状态RefundedState"),无需修改现有状态类和环境类(ContextState),符合"开放-封闭原则"。 -
状态逻辑可复用
不同环境类可共享同一个状态实例(如多个订单对象可共用
CompletedState实例),减少重复代码。
状态模式的优点
缺点
-
类数量增加
每个状态都需要对应一个类(如示例中有4个状态就有4个类),如果状态数量过多,会导致类的数量激增,增加系统复杂度。
-
状态切换依赖外部管理
状态的切换需要由环境类(
ContextState)或外部客户端(如StateTest)主动调用setState(),若状态切换逻辑复杂,可能需要额外的管理类来协调,否则容易出错。 -
状态间依赖可能隐含复杂性
若某些状态切换存在依赖关系(如"已发货"状态只能从"已支付"状态切换而来),需要在外部严格控制,否则可能出现不合理的状态转换(如直接从"待支付"跳到"已完成")。
总结
状态模式适合用于对象状态明确且状态间行为差异较大、状态切换频繁的场景(如订单状态、游戏角色状态等),能有效简化状态管理逻辑;但在状态数量极少或状态逻辑简单的场景中,可能会因类数量增加而显得冗余。