一、状态模式
概述
在状态模式(State Pattern)中,类的行为是基于它的状态改变的,这种类型的设计模式属于行为型模式
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象
状态模式允许对象在内部状态改变时改变其行为,使得对象在不同的状态下有不同的行为表现。通过将每个状态封装成独立的类,可以避免使用大量的条件语句来实现状态切换
主要解决:
状态模式解决对象行为依赖于其状态的问题,使得对象可以在状态变化时切换行为
何时使用:
- 当需要避免使用大量的条件语句来控制对象的行为时,状态模式可以提供一种更加优雅的解决方案
优缺点
优点:
- 封装状态转换规则:将状态转换逻辑封装在状态对象内部
- 易于扩展:增加新的状态类不会影响现有代码
- 集中状态相关行为:将所有与特定状态相关的行为集中到一个类中
- 简化条件语句:避免使用大量的条件语句来切换行为
- 状态共享:允许多个上下文对象共享同一个状态对象
缺点:
- 增加类和对象数量:每个状态都需要一个具体的状态类
- 实现复杂:模式结构和实现相对复杂
- 开闭原则支持不足:增加新状态或修改状态行为可能需要修改现有代码
注意事项
- 状态模式适用于状态数量有限(通常不超过5个)的情况
- 谨慎使用,以避免系统变得过于复杂
1. 各个角色介绍
1.1 上下文(Context)
- 定义了客户感兴趣的接口,并维护一个当前状态对象的引用。上下文可以通过状态对象来委托处理状态相关的行为
1.2 状态(State)
- 定义了一个接口,用于封装与上下文相关的一个状态的行为
1.3 具体状态(Concrete State)
- 实现了状态接口,负责处理与该状态相关的行为。具体状态对象通常会在内部维护一个对上下文对象的引用,以便根据不同的条件切换到不同的状态
2. UML图
我们将创建一个 State 接口和实现了 State 接口的实体状态类。Context 是一个带有某个状态的类
3. 具体例子和代码
角色分配
-
Context:上下文
-
State:状态
-
Concrete State:具体状态
3.1 上下文
- Context
package com.vinjcent.prototype.state;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author vinjcent
* @description 上下文
* @since 2024/5/29 21:41
*/
@Data
public class Context {
@ApiModelProperty("状态")
private State state;
public Context() {
state = null;
}
}
3.2 状态接口及其实现类
- State
package com.vinjcent.prototype.state;
/**
* @author vinjcent
* @description 状态接口
* @since 2024/5/29 21:41
*/
public interface State {
/**
* 执行动作
*
* @param context 上下文
*/
void doAction(Context context);
}
- StartState
package com.vinjcent.prototype.state;
/**
* @author vinjcent
* @description 开始状态
* @since 2024/5/29 21:43
*/
public class StartState implements State {
@Override
public void doAction(Context context) {
System.out.println("Player is in start state");
context.setState(this);
}
public String toString() {
return "Start State";
}
}
- StopState
package com.vinjcent.prototype.state;
/**
* @author vinjcent
* @description 终止状态
* @since 2024/5/29 21:43
*/
public class StopState implements State {
@Override
public void doAction(Context context) {
System.out.println("Player is in stop state");
context.setState(this);
}
public String toString() {
return "Stop State";
}
}
3.3 测试主函数
package com.vinjcent.prototype.state;
/**
* @author vinjcent
* @description 状态模式
* @since 2024/5/29 21:46
*/
public class Main {
public static void main(String[] args) {
// 上下文
Context context = new Context();
// 起始状态
StartState startState = new StartState();
// 将起始状态放入上下文中
startState.doAction(context);
System.out.println(context.getState().toString());
// 终止状态
StopState stopState = new StopState();
// 将终止状态放入上下文中
stopState.doAction(context);
System.out.println(context.getState().toString());
}
}
- 测试结果
4. 使用场景
- 当代码中存在大量条件语句,且这些条件语句依赖于对象的状态时