使用方法
public class Main {
enum Event {
START, STOP
}
/**
* @param args
*/
public static void main(String[] args) {
StateMachine stateMachine = new StateMachine();
A a = new A();
B b = new B();
a.linkTo(b, Event.START);
b.linkTo(a, Event.STOP);
stateMachine.addState(a);
stateMachine.addState(b);
stateMachine.setInitState(a);
stateMachine.start();
stateMachine.postEvent(Event.START);
stateMachine.postEvent(Event.STOP);
}
public static class A extends State {
public A() {
super("A");
}
@Override
public void onEnter(State fromState, Enum<?> event, Object data) {
System.out.println("----" + this);
System.out.println(fromState);
System.out.println(event.ordinal());
System.out.println(data);
}
}
public static class B extends State {
public B() {
super("B");
}
@Override
public void onEnter(State fromState, Enum<?> event, Object data) {
System.out.println("----" + this);
System.out.println(fromState);
System.out.println(event.ordinal());
System.out.println(data);
}
}
}
源码
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package my.home.common;
import java.util.HashMap;
/**
* Created by legendmohe on 15/12/5.
*/
public abstract class State {
HashMap<Enum<?>, State> mToStates = new HashMap<>();
private StateMachine mStateMachine;
@SuppressWarnings("unused")
private String mName = "UNKNOWN";
public State(String name) {
mName = name;
}
public void linkTo(State toState, Enum<?> event) {
if (toState == null) {
throw new IllegalArgumentException("toState cannot be null");
}
mToStates.put(event, toState);
}
public void onStart() {
}
public void onStop(int cause) {
}
public void onReset(int cause) {
}
public void onUnhandleEvent(Enum<?> event, Object data) {
}
public void onEnter(State fromState, Enum<?> event, Object data) {
}
public void onLeave(State toState, Enum<?> event, Object data) {
}
protected StateMachine getStateMachine() {
return mStateMachine;
}
protected void setStateMachine(StateMachine stateMachine) {
mStateMachine = stateMachine;
}
}
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package my.home.common;
import android.os.Handler;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
/**
* Created by legendmohe on 15/12/5.
*/
public class StateMachine {
Set<State> mStates = new HashSet<>();
private State mInitState;
private State mCurrentState;
private Object mHandleLock = new Object();
Handler mHandler;
public StateMachine() {
mHandler = new Handler();
}
public StateMachine(Handler handler) {
mHandler = handler;
}
public void setInitState(State initState) {
mInitState = initState;
}
public void addState(State state) {
synchronized (this) {
mStates.add(state);
state.setStateMachine(this);
}
}
public void start() {
synchronized (this) {
for (State state : mStates) {
state.onStart();
}
mCurrentState = mInitState;
}
}
public void stop(int cause) {
synchronized (this) {
for (State state : mStates) {
state.onStop(cause);
}
}
}
public void reset(int cause) {
synchronized (this) {
for (State state : mStates) {
state.onReset(cause);
}
mCurrentState = mInitState;
}
}
public void postEvent(Enum<?> event) {
postEvent(event , null);
}
public void postEvent(final Enum<?> event, final Object data) {
if (mHandler == null) {
return;
}
mHandler.post(new Runnable() {
@Override
public void run() {
synchronized (mHandleLock) {
State nextState = mCurrentState.mToStates.get(event);
if (nextState == null) {
mCurrentState.onUnhandleEvent(event, data);
return;
}
mCurrentState.onLeave(nextState, event, data);
nextState.onEnter(mCurrentState, event, data);
mCurrentState = nextState;
}
}
});
}
public boolean canMoveTo(State toState) {
if (toState == null) {
return false;
}
synchronized (this) {
HashMap<Enum<?>, State> states = mCurrentState.mToStates;
for (Enum<?> event : states.keySet()) {
if (states.get(event).equals(toState)) {
return true;
}
}
return false;
}
}
public boolean canAccept(Enum<?> event) {
synchronized (this) {
return mCurrentState.mToStates.containsKey(event);
}
}
public State getCurrentState() {
return mCurrentState;
}
}