设计模式之状态机模式

一、状态机模式介绍

状态机模式(State Machine Pattern)是一种用于描述对象行为的软件设计模式,属于行为型设计模式。在状态机模式中,对象的行为取决于其内部状态,并且在不同的状态下,对象可能会有不同的行为。这种模式通常涉及定义一组状态以及状态之间的转换规则,从而实现对对象行为的精确控制。

1、状态机模式的基本概念

状态机类图:

状态机模式主要包含以下几个要素:

  1. 状态(State):表示对象所处的特定状态。每个状态都定义了对象在该状态下的行为。
  2. 上下文(Context):上下文是包含状态机的对象。它维护了当前状态,并在状态之间的转换发生时更新状态。
  3. 转换(Transition):描述了对象从一个状态转移到另一个状态的过程。它通常受到一些条件或触发事件的影响。
  4. 动作(Action):动作是状态转换期间可能执行的操作或行为。这些动作可以是更新状态、执行计算、发送消息等。

2、状态机模式的特点

  1. 清晰的状态管理:通过明确定义系统的所有可能状态以及在这些状态之间的转换,帮助开发者清晰地管理和跟踪系统的状态。
  2. 简化复杂逻辑:将复杂的条件分支逻辑转换为状态图,使得逻辑更加直观易懂。
  3. 易于维护和扩展:状态机的结构使得对系统的修改和扩展变得更加容易。通过添加新的状态和转换规则,可以轻松适应需求的变化。
  4. 提高可测试性:由于状态机的行为是预定义的,因此可以更系统地进行测试,有助于确保系统的正确性和可靠性。

3、状态机模式的应用场景

状态机模式在多种应用场景中都有广泛的应用,包括但不限于以下几个方面:

  1. 游戏开发:用于游戏中的角色状态管理,如角色的移动、攻击、防御等状态。
  2. 嵌入式系统:用于描述设备的状态和状态转移,如自动售货机、电梯控制等。
  3. 网络通信:用于管理网络连接的状态,如连接建立、数据传输、连接关闭等。
  4. UI设计:用于管理UI元素的交互逻辑,如按钮的点击状态、表单的输入验证状态等。

二、状态机模式的实现例子

下面是一个简单的Java状态机模式例子。在这个例子中,我们将模拟一个简单的交通信号灯系统,它有三种状态:红灯(Red)、绿灯(Green)、黄灯(Yellow)。每个状态都有一个特定的行为,即打印出当前灯的颜色,并且每个状态都可以转换到下一个状态。

首先,我们定义一个TrafficLightState接口,它表示交通信号灯的所有可能状态:

public interface TrafficLightState {  
    void change(TrafficLightContext context);  
}

然后,我们为每种状态实现这个接口:

public class RedLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("红灯亮");  
        context.setState(new GreenLightState());  
    }  
}  
  
public class GreenLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("绿灯亮");  
        context.setState(new YellowLightState());  
    }  
}  
  
public class YellowLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("黄灯亮");  
        context.setState(new RedLightState());  
    }  
}

接下来,我们定义TrafficLightContext类,它包含了当前的状态,并且提供了一个方法来改变状态:

public class TrafficLightContext {  
    private TrafficLightState state;  
  
    public TrafficLightContext() {  
        this.state = new RedLightState();  
    }  
  
    public void setState(TrafficLightState state) {  
        this.state = state;  
    }  
  
    public void change() {  
        state.change(this);  
    }  
}

最后,我们创建一个客户端来模拟交通信号灯的状态变化:

public class Client {  
    public static void main(String[] args) {  
        TrafficLightContext context = new TrafficLightContext();  
          
        // 模拟状态变化  
        context.change();  
        context.change();  
        context.change();  
        context.change();  
        context.change();  
    }  
}

在这个例子中,TrafficLightContext类维护了当前的交通信号灯状态,并且提供了一个change方法来改变状态。每个状态类都实现了TrafficLightState接口,并且在其change方法中定义了下一个状态。客户端通过调用TrafficLightContextchange方法来模拟交通信号灯的状态变化。 

现实中的状态转变,比这个复杂多了,一个状态节点可能有多个action操作,类似订单状态的流转,无法直接套用状态机模式,应该有记录状态变迁的全景图(核心要素:当前状态,当前状态可选动作,动作执行后状态迁移)。

以下是一个简单的例子,记录当前状态,可选动作及执行动作后状态的一个例子,用于约束状态的变迁,。

package demo;

import java.util.HashMap;
import java.util.Map;

public class StateMachine {

	/**
	 * key:当前状态 ,value: Map<String, String>,可选的动作及后续状态,key:xxxAction,value:nextState
	 */
	private Map<String, Map<String, String>> stateMap;

	public StateMachine() {
		stateMap = new HashMap<String, Map<String, String>>();

		// 初始状态可以执行的Action及执行后的动作
		Map<String, String> initActionMap = new HashMap<String, String>();
		initActionMap.put("runAction", "run");
		stateMap.put("init", initActionMap);

		// run状态下可以执行的动作
		Map<String, String> runActionMap = new HashMap<String, String>();
		runActionMap.put("stopAction", "stop");
		runActionMap.put("sleepAction", "sleep");
		runActionMap.put("endAction", "end");
		stateMap.put("run", runActionMap);

		// sleep状态下可以执行的动作
		Map<String, String> sleepActionMap = new HashMap<String, String>();
		sleepActionMap.put("runAction", "run");
		stateMap.put("sleep", sleepActionMap);

		// stop状态下可以执行的动作
		Map<String, String> stopActionMap = new HashMap<String, String>();
		stopActionMap.put("runAction", "run");
		stateMap.put("stop", stopActionMap);

	}

	public String getNextState(String curState, String action) {
		Map<String, String> curStateMap = stateMap.get(curState);
		if (curStateMap == null) {
			System.out.println("curState error");
			return "";
		}

		String nextState = curStateMap.get(action);
		if (nextState == null) {
			System.out.println("acction error");
			return "";
		}
		return nextState;
	}

	public static void main(String[] args) {
		StateMachine sm = new StateMachine();
		String nextState = sm.getNextState("init", "runAction");
		System.out.println(nextState);
		nextState = sm.getNextState("run", "stopAction");
		System.out.println(nextState);
		nextState = sm.getNextState("stop", "runAction");
		System.out.println(nextState);
		nextState = sm.getNextState("run", "endAction");
		System.out.println(nextState);
	}

}

三、总结

        状态机模式是一种强大的工具,能够帮助开发者在软件开发中处理复杂的逻辑和状态管理问题。通过明确定义系统的状态和转换规则,状态机模式使得系统的行为更加清晰、可控和易于维护。同时,状态机模式还具有广泛的应用场景和灵活的实现方式,适用于多种复杂的软件开发需求。

如果状态模式对你有用,记得点赞收藏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值