状态模式:当一个对象的内在状态改变时,允许改变其行为。状态模式中行为是由状态来决定的,不同的状态下有不同的行为。状态模式的意图是让一个对象在其内部状态改变时,其行为也随之改变。
状态模式的UML类图:
Context:环境类,定义客户感兴趣的接口,维护一个State子类的实例,这个实例定义了对象的当前状态。
State:抽象状态类或者状态接口,定义一个或者一组接口,表示该状态下的行为。
ConcreteStateA、ConcreteStateB:具体状态类,每一个具体的状态类实现抽象State中定义的接口,从而达到不同状态下的不同行为。
接下来我们将分析Android中的StateMachine实现。首先看下StateMachine的UML类图,从图中可以看到,StateMachine的UML类图符合状态模式的设计原则,IState接口代表一组接口,表示该状态下的行为。HaltingState和QuittingState代表具体的状态,StateMachine对象维护当前状态,提供客户端感兴趣的接口。
IState接口定义在frameworks/core/java/com/android/internal/util/IState.java中
State接口定义frameworks/core/java/com/android/internal/util/State.java类中
StateMachine类定义在frameworks/core/java/com/android/internal/util/StateMachine.java中。
IState接口
IState接口定义了一组方法,表示该状态下的行为。
- enter()
- exit()
- processMessage()
- getName()
State类
State类提供一个IState接口的基本实现。State类必须实现processMessage方法,可选地实现enter和exit函数,这两个方法等价于构造函数和析构函数,用于初始化和清理相关的工作。
StateMachine类
StateMachine是一个层次式状态机,可以管理和处理状态的跳转。StateMachine是基于Handler来实现的,通过Message来驱动状态的跳转。首先来看下状态机的构建:
/**
* 状态机的构建函数
*
* @param name 状态机的名字
*/
protected StateMachine(String name) {
//通过HandlerThread来处理消息
mSmThread = new HandlerThread(name);
mSmThread.start();
Looper looper = mSmThread.getLooper();
initStateMachine(name, looper);
}
/**
* 初始化状态机
*
* @param looper 状态机使用的Looper
* @param name 状态机名字
*/
private void initStateMachine(String name, Looper looper) {
mName = name;
mSmHandler = new SmHandler(looper, this);
}
/*
* SmHandler继承自Handler
*/
private SmHandler(Looper looper, StateMachine sm) {
super(looper);
mSm = sm;//持有一个状态机的引用
//将Halting和Quitting状态添加到状态列表中
addState(mHaltingState, null);
addState(mQuittingState, null);
}
当一个状态机被创建,通过addState函数来构建状态的层级,通过setInitialState函数来设置初始状态。
/**
* 添加一个新的状态到状态机
*
*
* @param 需要添加的状态
* @param parent the 状态的父状态
* @return stateInfo 返回当前状态的信息
*/
private final StateInfo addState(State state, State parent) {
StateInfo parentStateInfo = null;
if (parent != null) {
parentStateInfo = mStateInfo.get(parent);
if (parentStateInfo == null) {
//如果parent状态还未添加,则先添加parent状态
parentStateInfo = addState(parent, null);
}
}
StateInfo stateInfo = mStateInfo.get(state);
if (stateInfo == null) {
stateInfo = new StateInfo();
//将状态添加到状态集合中
mStateInfo.put(state, stateInfo);
}
//验证是否存在相同的状态,不同parent的情况,保证一个状态只有一个parent状态存在
if ((stateInfo.parentStateInfo != null)
&& (stateInfo.parentStateInfo != parentStateInfo)) {
throw new RuntimeException("state already added");
}
stateInfo.state = state;
stateInfo.parentStateInfo = parentStateInfo;
stateInfo.active = false;
return stateInfo;
}
/*
* 状态信息
*/
private class StateInfo {
/** 状态 */
State state;
/** 父类状态信息,如果没有父类状态,则为空 */
StateInfo parentStateInfo;
/** True when the state has been entered and on the stack */
boolean active;
/**
* Convert StateInfo to string
*/
@Override
public String toString() {
return "state=" + state.getName() + ",active=" + active + ",parent="
+ ((parentStateInfo == null) ? "null" : pa