Related
I've been reading up on State Machines since its likely I need to use for my next project. Most examples I find online show how to go from StateA to StateB. But what if your next desired state is not an adjacent state? Are there any common patterns/practices to achieve this? Ideally in Java, but I can read other programming languages just as well.
# Example States
WakeUp->Get Dressed->Get Car Keys->Get in Car->Drive to Work->Work
Current State: Get in Car
Problems to solve
# Scenario 1: Desired State == Work
Forgot car keys, so you have to return to previous state and then move forward in states again.
# Scenario 2: Desired State == Work
Have car keys, so move forward in states to get to Desired State.
It's very likely that State Machine may not solve this problem elegantly and I just need to hand-craft the logic, I don't mind, but thought I'd follow a common design pattern to help others understand it.
From the example above, I do not need to worry about 'internal' states, which is also true for the project I'm tackling; just in case that makes a difference in possible solutions.
Here is a simple way to define a state machine.
Define in an enum all the states that you want.
enum StateType {
WAKE_UP, GET_DRESSED, GET_CAR_KEYS, GET_IN_CAR, DRIVE_TO_WORK, WORK
}
Have a statemachine which controls states, and a state interface which performs an action on the statemachine. The state then returns the next state to go to.
interface State {
StateType next(StateMachine sm);
}
Implement this state for multiple types
class GetInCarState implements State {
#Override
public StateType next(StateMachine sm) {
if (sm.hasKeys()) {
return StateType.DRIVE_TO_WORK;
}
return StateType.GET_CAR_KEYS;
}
}
Now define the State Machine
class StateMachine {
private Map<StateType, State> states = new HashMap<StateType, State>() {{
put(StateType.WAKE_UP, new WakeUpState());
put(StateType.GET_DRESSED, new GetDressedState());
put(StateType.GET_CAR_KEYS, new GetCarKeysState());
put(StateType.GET_IN_CAR, new GetInCarState());
put(StateType.DRIVE_TO_WORK, new DriveToWorkState());
put(StateType.WORK, new WorkState());
}};
private StateType currentState = StateType.WAKE_UP;
private boolean hasCarKeys;
public boolean hasKeys() {
return hasCarKeys;
}
public void setHasKeys(boolean hasKeys) {
hasCarKeys = hasKeys;
}
public void update() {
currentState = states.get(currentState).next(this);
}
}
I am making a multiplayer game which makes heavy use of a serialisable Event class to send messages over a network. I want to be able to reconstruct the appropriate subclass of Event based on a constant.
So far I have opted for the following solution:
public class EventFactory {
public static Event getEvent(int eventId, ByteBuffer buf) {
switch (eventId){
case Event.ID_A:
return EventA.deserialise(buf);
case Event.ID_B:
return EventB.deserialise(buf);
case Event.ID_C:
return EventC.deserialise(buf);
default:
// Unknown Event ID
return null;
}
}
}
However, this strikes me as being very verbose and involves adding a new 'case' statement every time I create a new Event type.
I am aware of 2 other ways of accomplishing this, but neither seems better*:
Create a mapping of constants -> Event subclasses, and use clazz.newInstance() to instantiate them (using an empty constructor), followed by clazz.initialiase(buf) to supply the necessary parameters.
Create a mapping of constants -> Event subclasses, and use reflection to find and call the right method in the appropriate class.
Is there a better approach than the one I am using? Am I perhaps unwise to disregard the alternatives mentioned above?
*NOTE: in this case better means simpler / cleaner but without compromising too much on speed.
You can just use a HashMap<Integer,Event> to get the correct Event for the eventID. Adding or removing events is going to be easy, and as the code grows this is easy to maintain when compared to switch case solution and speed wise also this should be faster than switch case solution.
static
{
HashMap<Integer,Event> eventHandlerMap = new HashMap<>();
eventHandlerMap.put(eventId_A, new EventHandlerA());
eventHandlerMap.put(eventId_B, new EventHandlerB());
............
}
Instead of your switch statement Now you can just use :
Event event = eventHandlerMap.get(eventId);
if(event!=null){
event.deserialise(buf);
}
If you're not afraid of reflection, you could use:
private static final Map<Integer, Method> EVENTID_METHOD_MAP = new LinkedHashMap<>();
static {
try {
for (Field field : Event.class.getFields())
if (field.getName().startsWith("ID_")) {
String classSuffix = field.getName().substring(3);
Class<?> cls = Class.forName("Event" + classSuffix);
Method method = cls.getMethod("deserialize", ByteBuffer.class);
EVENTID_METHOD_MAP.put(field.getInt(null), method);
}
} catch (IllegalAccessException|ClassNotFoundException|NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
public static Event getEvent(int eventId, ByteBuffer buf)
throws InvocationTargetException, IllegalAccessException {
return (Event) EVENTID_METHOD_MAP.get(eventId).invoke(null, buf);
}
This solution requires that int ID_N always maps to class EventN, where N can be any String where all characters return true for the method java.lang.Character.isJavaIdentifierPart(c). Also, class EventN must define a static method called deserialize with one ByteBuffer argument that returns an Event.
You could also check if field is static before trying to get its field value. I just forget how to do that at the moment.
I have something to do for work and I need your help.
We want to implement a FSM - Finite State Machine, to identify char sequence(like: A, B, C, A, C), and tell if it accepted.
We think to implement three classes: State, Event and Machine.
The state class presents a node in the FSM, we thought to implement it with State design pattern, every node will extend from the abstract class state and every class would handle different types of events and indicate transitions to a new state. Is it good idea in your opinion?
Second thing, we don't know how to save all the transitions. Again we thought to implement it with some kind of map, that hold the starting point and gets some kind of vector with the next states, but I'm not sure thats a good idea.
I would be happy to get some ideas of how to implement it or maybe you can give me some starting points.
How should I save the FSM, meaning how should I build the tree at the beginning of the program?
I googled it and found a lot of examples but nothing that helps me.
Thanks a lot.
The heart of a state machine is the transition table, which takes a state and a symbol (what you're calling an event) to a new state. That's just a two-index array of states. For sanity and type safety, declare the states and symbols as enumerations. I always add a "length" member in some way (language-specific) for checking array bounds. When I've hand-coded FSM's, I format the code in row and column format with whitespace fiddling. The other elements of a state machine are the initial state and the set of accepting states. The most direct implementation of the set of accepting states is an array of booleans indexed by the states. In Java, however, enumerations are classes, and you can specify an argument "accepting" in the declaration for each enumerated value and initialize it in the constructor for the enumeration.
For the machine type, you can write it as a generic class. It would take two type arguments, one for the states and one for the symbols, an array argument for the transition table, a single state for the initial. The only other detail (though it's critical) is that you have to call Enum.ordinal() to get an integer suitable for indexing the transition array, since you there's no syntax for directly declaring an array with a enumeration index (though there ought to be).
To preempt one issue, EnumMap won't work for the transition table, because the key required is a pair of enumeration values, not a single one.
enum State {
Initial( false ),
Final( true ),
Error( false );
static public final Integer length = 1 + Error.ordinal();
final boolean accepting;
State( boolean accepting ) {
this.accepting = accepting;
}
}
enum Symbol {
A, B, C;
static public final Integer length = 1 + C.ordinal();
}
State transition[][] = {
// A B C
{
State.Initial, State.Final, State.Error
}, {
State.Final, State.Initial, State.Error
}
};
EasyFSM is a dynamic Java Library which can be used to implement an FSM.
You can find documentation for the same at :
Finite State Machine in Java
Also, you can download the library at :
Java FSM Library : DynamicEasyFSM
You can implement Finite State Machine in two different ways.
Option 1:
Finite State machine with a pre-defined workflow : Recommended if you know all states in advance and state machine is almost fixed without any changes in future
Identify all possible states in your application
Identify all the events in your application
Identify all the conditions in your application, which may lead state transition
Occurrence of an event may cause transitions of state
Build a finite state machine by deciding a workflow of states & transitions.
e.g If an event 1 occurs at State 1, the state will be updated and machine state may still be in state 1.
If an event 2 occurs at State 1, on some condition evaluation, the system will move from State 1 to State 2
This design is based on State and Context patterns.
Have a look at Finite State Machine prototype classes.
Option 2:
Behavioural trees: Recommended if there are frequent changes to state machine workflow. You can dynamically add new behaviour without breaking the tree.
The base Task class provides a interface for all these tasks, the leaf tasks are the ones just mentioned, and the parent tasks are the interior nodes that decide which task to execute next.
The Tasks have only the logic they need to actually do what is required of them, all the decision logic of whether a task has started or not, if it needs to update, if it has finished with success, etc. is grouped in the TaskController class, and added by composition.
The decorators are tasks that “decorate” another class by wrapping over it and giving it additional logic.
Finally, the Blackboard class is a class owned by the parent AI that every task has a reference to. It works as a knowledge database for all the leaf tasks
Have a look at this article by Jaime Barrachina Verdia for more details
Hmm, I would suggest that you use Flyweight to implement the states. Purpose: Avoid the memory overhead of a large number of small objects. State machines can get very, very big.
http://en.wikipedia.org/wiki/Flyweight_pattern
I'm not sure that I see the need to use design pattern State to implement the nodes. The nodes in a state machine are stateless. They just match the current input symbol to the available transitions from the current state. That is, unless I have entirely forgotten how they work (which is a definite possiblilty).
If I were coding it, I would do something like this:
interface FsmNode {
public boolean canConsume(Symbol sym);
public FsmNode consume(Symbol sym);
// Other methods here to identify the state we are in
}
List<Symbol> input = getSymbols();
FsmNode current = getStartState();
for (final Symbol sym : input) {
if (!current.canConsume(sym)) {
throw new RuntimeException("FSM node " + current + " can't consume symbol " + sym);
}
current = current.consume(sym);
}
System.out.println("FSM consumed all input, end state is " + current);
What would Flyweight do in this case? Well, underneath the FsmNode there would probably be something like this:
Map<Integer, Map<Symbol, Integer>> fsm; // A state is an Integer, the transitions are from symbol to state number
FsmState makeState(int stateNum) {
return new FsmState() {
public FsmState consume(final Symbol sym) {
final Map<Symbol, Integer> transitions = fsm.get(stateNum);
if (transisions == null) {
throw new RuntimeException("Illegal state number " + stateNum);
}
final Integer nextState = transitions.get(sym); // May be null if no transition
return nextState;
}
public boolean canConsume(final Symbol sym) {
return consume(sym) != null;
}
}
}
This creates the State objects on a need-to-use basis, It allows you to use a much more efficient underlying mechanism to store the actual state machine. The one I use here (Map(Integer, Map(Symbol, Integer))) is not particulary efficient.
Note that the Wikipedia page focuses on the cases where many somewhat similar objects share the similar data, as is the case in the String implementation in Java. In my opinion, Flyweight is a tad more general, and covers any on-demand creation of objects with a short life span (use more CPU to save on a more efficient underlying data structure).
Consider the easy, lightweight Java library EasyFlow. From their docs:
With EasyFlow you can:
implement complex logic but keep your code simple and clean
handle asynchronous calls with ease and elegance
avoid concurrency by using event-driven programming approach
avoid StackOverflow error by avoiding recursion
simplify design, programming and testing of complex java applications
I design & implemented a simple finite state machine example with java.
IFiniteStateMachine: The public interface to manage the finite state machine
such as add new states to the finite state machine or transit to next states by specific actions.
interface IFiniteStateMachine {
void setStartState(IState startState);
void setEndState(IState endState);
void addState(IState startState, IState newState, Action action);
void removeState(String targetStateDesc);
IState getCurrentState();
IState getStartState();
IState getEndState();
void transit(Action action);
}
IState: The public interface to get state related info
such as state name and mappings to connected states.
interface IState {
// Returns the mapping for which one action will lead to another state
Map<String, IState> getAdjacentStates();
String getStateDesc();
void addTransit(Action action, IState nextState);
void removeTransit(String targetStateDesc);
}
Action: the class which will cause the transition of states.
public class Action {
private String mActionName;
public Action(String actionName) {
mActionName = actionName;
}
String getActionName() {
return mActionName;
}
#Override
public String toString() {
return mActionName;
}
}
StateImpl: the implementation of IState. I applied data structure such as HashMap to keep Action-State mappings.
public class StateImpl implements IState {
private HashMap<String, IState> mMapping = new HashMap<>();
private String mStateName;
public StateImpl(String stateName) {
mStateName = stateName;
}
#Override
public Map<String, IState> getAdjacentStates() {
return mMapping;
}
#Override
public String getStateDesc() {
return mStateName;
}
#Override
public void addTransit(Action action, IState state) {
mMapping.put(action.toString(), state);
}
#Override
public void removeTransit(String targetStateDesc) {
// get action which directs to target state
String targetAction = null;
for (Map.Entry<String, IState> entry : mMapping.entrySet()) {
IState state = entry.getValue();
if (state.getStateDesc().equals(targetStateDesc)) {
targetAction = entry.getKey();
}
}
mMapping.remove(targetAction);
}
}
FiniteStateMachineImpl: Implementation of IFiniteStateMachine. I use ArrayList to keep all the states.
public class FiniteStateMachineImpl implements IFiniteStateMachine {
private IState mStartState;
private IState mEndState;
private IState mCurrentState;
private ArrayList<IState> mAllStates = new ArrayList<>();
private HashMap<String, ArrayList<IState>> mMapForAllStates = new HashMap<>();
public FiniteStateMachineImpl(){}
#Override
public void setStartState(IState startState) {
mStartState = startState;
mCurrentState = startState;
mAllStates.add(startState);
// todo: might have some value
mMapForAllStates.put(startState.getStateDesc(), new ArrayList<IState>());
}
#Override
public void setEndState(IState endState) {
mEndState = endState;
mAllStates.add(endState);
mMapForAllStates.put(endState.getStateDesc(), new ArrayList<IState>());
}
#Override
public void addState(IState startState, IState newState, Action action) {
// validate startState, newState and action
// update mapping in finite state machine
mAllStates.add(newState);
final String startStateDesc = startState.getStateDesc();
final String newStateDesc = newState.getStateDesc();
mMapForAllStates.put(newStateDesc, new ArrayList<IState>());
ArrayList<IState> adjacentStateList = null;
if (mMapForAllStates.containsKey(startStateDesc)) {
adjacentStateList = mMapForAllStates.get(startStateDesc);
adjacentStateList.add(newState);
} else {
mAllStates.add(startState);
adjacentStateList = new ArrayList<>();
adjacentStateList.add(newState);
}
mMapForAllStates.put(startStateDesc, adjacentStateList);
// update mapping in startState
for (IState state : mAllStates) {
boolean isStartState = state.getStateDesc().equals(startState.getStateDesc());
if (isStartState) {
startState.addTransit(action, newState);
}
}
}
#Override
public void removeState(String targetStateDesc) {
// validate state
if (!mMapForAllStates.containsKey(targetStateDesc)) {
throw new RuntimeException("Don't have state: " + targetStateDesc);
} else {
// remove from mapping
mMapForAllStates.remove(targetStateDesc);
}
// update all state
IState targetState = null;
for (IState state : mAllStates) {
if (state.getStateDesc().equals(targetStateDesc)) {
targetState = state;
} else {
state.removeTransit(targetStateDesc);
}
}
mAllStates.remove(targetState);
}
#Override
public IState getCurrentState() {
return mCurrentState;
}
#Override
public void transit(Action action) {
if (mCurrentState == null) {
throw new RuntimeException("Please setup start state");
}
Map<String, IState> localMapping = mCurrentState.getAdjacentStates();
if (localMapping.containsKey(action.toString())) {
mCurrentState = localMapping.get(action.toString());
} else {
throw new RuntimeException("No action start from current state");
}
}
#Override
public IState getStartState() {
return mStartState;
}
#Override
public IState getEndState() {
return mEndState;
}
}
example:
public class example {
public static void main(String[] args) {
System.out.println("Finite state machine!!!");
IState startState = new StateImpl("start");
IState endState = new StateImpl("end");
IFiniteStateMachine fsm = new FiniteStateMachineImpl();
fsm.setStartState(startState);
fsm.setEndState(endState);
IState middle1 = new StateImpl("middle1");
middle1.addTransit(new Action("path1"), endState);
fsm.addState(startState, middle1, new Action("path1"));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.transit(new Action(("path1")));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.addState(middle1, endState, new Action("path1-end"));
fsm.transit(new Action(("path1-end")));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.addState(endState, middle1, new Action("path1-end"));
}
}
Full example on Github
Well this is an old question but while nobody mentioned here, I will advice to check two existing frameworks before you implement you own State Machines.
One is Spring State Machine most of you are familiar with Spring framework, which allow us to use several features of Spring like dependency injection and everything else that Spring can offer.
It is really great for modelling the lifecycle of an Apparat, with states like INITIALIZING, STARTED, ERROR, RECOVERING, SHUTTINGDOWN, etc.. but I see lots of people are trying to model a Shopping Chart, a Reservation System with it, the memory footprint a Spring State Machine is relatively big to model millions of Shopping Charts or Reservations.
One other disadvantage, Spring State Machine, while has a capability to persist itself for long running processes but it does not have any mechanism to adapt to changes in these processes, if you persist a process and you have to recover it lets say 10 days later with a change occurred in your business process because of new software release / requirement, you have no built in means to deal with it.
I have several blogs, blog1 blog2, demonstrating how you can program Spring State Machine, specially model driven way, if you want to check it.
Mainly because the disadvantages I mentioned, I advice you to look another framework first, Akka FSM (Finite State Machine) which is more fitting with its low memory footprint to have millions and millions of instances and has a capability to adapt changing long running processes.
Now you can develop with Akka framework with Java but believe me because of some missing language elements, you don't want to read the produced code, Scala is a much more fitting language to develop with Akka. Now I hear you saying Scala is too complex, I can't convince my project leads to develop with Scala, to convince you all this is an option, I developed a Proof of Concept application using a Java/Scala hybrid with all Scala Akka Finite State Machine code generated from an UML model, if you want to check it out here the links to the blogs, blog3 blog4.
I hope this information would help you.
Here is a SUPER SIMPLE implementation/example of a FSM using just "if-else"s which avoids all of the above subclassing answers (taken from Using Finite State Machines for Pattern Matching in Java, where he is looking for a string which ends with "#" followed by numbers followed by "#"--see state graph here):
public static void main(String[] args) {
String s = "A1#312#";
String digits = "0123456789";
int state = 0;
for (int ind = 0; ind < s.length(); ind++) {
if (state == 0) {
if (s.charAt(ind) == '#')
state = 1;
} else {
boolean isNumber = digits.indexOf(s.charAt(ind)) != -1;
if (state == 1) {
if (isNumber)
state = 2;
else if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
} else if (state == 2) {
if (s.charAt(ind) == '#') {
state = 3;
} else if (isNumber) {
state = 2;
} else if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
} else if (state == 3) {
if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
}
}
} //end for loop
if (state == 3)
System.out.println("It matches");
else
System.out.println("It does not match");
}
P.S: Does not answer your question directly, but shows you how to implement a FSM very easily in Java.
I have something to do for work and I need your help.
We want to implement a FSM - Finite State Machine, to identify char sequence(like: A, B, C, A, C), and tell if it accepted.
We think to implement three classes: State, Event and Machine.
The state class presents a node in the FSM, we thought to implement it with State design pattern, every node will extend from the abstract class state and every class would handle different types of events and indicate transitions to a new state. Is it good idea in your opinion?
Second thing, we don't know how to save all the transitions. Again we thought to implement it with some kind of map, that hold the starting point and gets some kind of vector with the next states, but I'm not sure thats a good idea.
I would be happy to get some ideas of how to implement it or maybe you can give me some starting points.
How should I save the FSM, meaning how should I build the tree at the beginning of the program?
I googled it and found a lot of examples but nothing that helps me.
Thanks a lot.
The heart of a state machine is the transition table, which takes a state and a symbol (what you're calling an event) to a new state. That's just a two-index array of states. For sanity and type safety, declare the states and symbols as enumerations. I always add a "length" member in some way (language-specific) for checking array bounds. When I've hand-coded FSM's, I format the code in row and column format with whitespace fiddling. The other elements of a state machine are the initial state and the set of accepting states. The most direct implementation of the set of accepting states is an array of booleans indexed by the states. In Java, however, enumerations are classes, and you can specify an argument "accepting" in the declaration for each enumerated value and initialize it in the constructor for the enumeration.
For the machine type, you can write it as a generic class. It would take two type arguments, one for the states and one for the symbols, an array argument for the transition table, a single state for the initial. The only other detail (though it's critical) is that you have to call Enum.ordinal() to get an integer suitable for indexing the transition array, since you there's no syntax for directly declaring an array with a enumeration index (though there ought to be).
To preempt one issue, EnumMap won't work for the transition table, because the key required is a pair of enumeration values, not a single one.
enum State {
Initial( false ),
Final( true ),
Error( false );
static public final Integer length = 1 + Error.ordinal();
final boolean accepting;
State( boolean accepting ) {
this.accepting = accepting;
}
}
enum Symbol {
A, B, C;
static public final Integer length = 1 + C.ordinal();
}
State transition[][] = {
// A B C
{
State.Initial, State.Final, State.Error
}, {
State.Final, State.Initial, State.Error
}
};
EasyFSM is a dynamic Java Library which can be used to implement an FSM.
You can find documentation for the same at :
Finite State Machine in Java
Also, you can download the library at :
Java FSM Library : DynamicEasyFSM
You can implement Finite State Machine in two different ways.
Option 1:
Finite State machine with a pre-defined workflow : Recommended if you know all states in advance and state machine is almost fixed without any changes in future
Identify all possible states in your application
Identify all the events in your application
Identify all the conditions in your application, which may lead state transition
Occurrence of an event may cause transitions of state
Build a finite state machine by deciding a workflow of states & transitions.
e.g If an event 1 occurs at State 1, the state will be updated and machine state may still be in state 1.
If an event 2 occurs at State 1, on some condition evaluation, the system will move from State 1 to State 2
This design is based on State and Context patterns.
Have a look at Finite State Machine prototype classes.
Option 2:
Behavioural trees: Recommended if there are frequent changes to state machine workflow. You can dynamically add new behaviour without breaking the tree.
The base Task class provides a interface for all these tasks, the leaf tasks are the ones just mentioned, and the parent tasks are the interior nodes that decide which task to execute next.
The Tasks have only the logic they need to actually do what is required of them, all the decision logic of whether a task has started or not, if it needs to update, if it has finished with success, etc. is grouped in the TaskController class, and added by composition.
The decorators are tasks that “decorate” another class by wrapping over it and giving it additional logic.
Finally, the Blackboard class is a class owned by the parent AI that every task has a reference to. It works as a knowledge database for all the leaf tasks
Have a look at this article by Jaime Barrachina Verdia for more details
Hmm, I would suggest that you use Flyweight to implement the states. Purpose: Avoid the memory overhead of a large number of small objects. State machines can get very, very big.
http://en.wikipedia.org/wiki/Flyweight_pattern
I'm not sure that I see the need to use design pattern State to implement the nodes. The nodes in a state machine are stateless. They just match the current input symbol to the available transitions from the current state. That is, unless I have entirely forgotten how they work (which is a definite possiblilty).
If I were coding it, I would do something like this:
interface FsmNode {
public boolean canConsume(Symbol sym);
public FsmNode consume(Symbol sym);
// Other methods here to identify the state we are in
}
List<Symbol> input = getSymbols();
FsmNode current = getStartState();
for (final Symbol sym : input) {
if (!current.canConsume(sym)) {
throw new RuntimeException("FSM node " + current + " can't consume symbol " + sym);
}
current = current.consume(sym);
}
System.out.println("FSM consumed all input, end state is " + current);
What would Flyweight do in this case? Well, underneath the FsmNode there would probably be something like this:
Map<Integer, Map<Symbol, Integer>> fsm; // A state is an Integer, the transitions are from symbol to state number
FsmState makeState(int stateNum) {
return new FsmState() {
public FsmState consume(final Symbol sym) {
final Map<Symbol, Integer> transitions = fsm.get(stateNum);
if (transisions == null) {
throw new RuntimeException("Illegal state number " + stateNum);
}
final Integer nextState = transitions.get(sym); // May be null if no transition
return nextState;
}
public boolean canConsume(final Symbol sym) {
return consume(sym) != null;
}
}
}
This creates the State objects on a need-to-use basis, It allows you to use a much more efficient underlying mechanism to store the actual state machine. The one I use here (Map(Integer, Map(Symbol, Integer))) is not particulary efficient.
Note that the Wikipedia page focuses on the cases where many somewhat similar objects share the similar data, as is the case in the String implementation in Java. In my opinion, Flyweight is a tad more general, and covers any on-demand creation of objects with a short life span (use more CPU to save on a more efficient underlying data structure).
Consider the easy, lightweight Java library EasyFlow. From their docs:
With EasyFlow you can:
implement complex logic but keep your code simple and clean
handle asynchronous calls with ease and elegance
avoid concurrency by using event-driven programming approach
avoid StackOverflow error by avoiding recursion
simplify design, programming and testing of complex java applications
I design & implemented a simple finite state machine example with java.
IFiniteStateMachine: The public interface to manage the finite state machine
such as add new states to the finite state machine or transit to next states by specific actions.
interface IFiniteStateMachine {
void setStartState(IState startState);
void setEndState(IState endState);
void addState(IState startState, IState newState, Action action);
void removeState(String targetStateDesc);
IState getCurrentState();
IState getStartState();
IState getEndState();
void transit(Action action);
}
IState: The public interface to get state related info
such as state name and mappings to connected states.
interface IState {
// Returns the mapping for which one action will lead to another state
Map<String, IState> getAdjacentStates();
String getStateDesc();
void addTransit(Action action, IState nextState);
void removeTransit(String targetStateDesc);
}
Action: the class which will cause the transition of states.
public class Action {
private String mActionName;
public Action(String actionName) {
mActionName = actionName;
}
String getActionName() {
return mActionName;
}
#Override
public String toString() {
return mActionName;
}
}
StateImpl: the implementation of IState. I applied data structure such as HashMap to keep Action-State mappings.
public class StateImpl implements IState {
private HashMap<String, IState> mMapping = new HashMap<>();
private String mStateName;
public StateImpl(String stateName) {
mStateName = stateName;
}
#Override
public Map<String, IState> getAdjacentStates() {
return mMapping;
}
#Override
public String getStateDesc() {
return mStateName;
}
#Override
public void addTransit(Action action, IState state) {
mMapping.put(action.toString(), state);
}
#Override
public void removeTransit(String targetStateDesc) {
// get action which directs to target state
String targetAction = null;
for (Map.Entry<String, IState> entry : mMapping.entrySet()) {
IState state = entry.getValue();
if (state.getStateDesc().equals(targetStateDesc)) {
targetAction = entry.getKey();
}
}
mMapping.remove(targetAction);
}
}
FiniteStateMachineImpl: Implementation of IFiniteStateMachine. I use ArrayList to keep all the states.
public class FiniteStateMachineImpl implements IFiniteStateMachine {
private IState mStartState;
private IState mEndState;
private IState mCurrentState;
private ArrayList<IState> mAllStates = new ArrayList<>();
private HashMap<String, ArrayList<IState>> mMapForAllStates = new HashMap<>();
public FiniteStateMachineImpl(){}
#Override
public void setStartState(IState startState) {
mStartState = startState;
mCurrentState = startState;
mAllStates.add(startState);
// todo: might have some value
mMapForAllStates.put(startState.getStateDesc(), new ArrayList<IState>());
}
#Override
public void setEndState(IState endState) {
mEndState = endState;
mAllStates.add(endState);
mMapForAllStates.put(endState.getStateDesc(), new ArrayList<IState>());
}
#Override
public void addState(IState startState, IState newState, Action action) {
// validate startState, newState and action
// update mapping in finite state machine
mAllStates.add(newState);
final String startStateDesc = startState.getStateDesc();
final String newStateDesc = newState.getStateDesc();
mMapForAllStates.put(newStateDesc, new ArrayList<IState>());
ArrayList<IState> adjacentStateList = null;
if (mMapForAllStates.containsKey(startStateDesc)) {
adjacentStateList = mMapForAllStates.get(startStateDesc);
adjacentStateList.add(newState);
} else {
mAllStates.add(startState);
adjacentStateList = new ArrayList<>();
adjacentStateList.add(newState);
}
mMapForAllStates.put(startStateDesc, adjacentStateList);
// update mapping in startState
for (IState state : mAllStates) {
boolean isStartState = state.getStateDesc().equals(startState.getStateDesc());
if (isStartState) {
startState.addTransit(action, newState);
}
}
}
#Override
public void removeState(String targetStateDesc) {
// validate state
if (!mMapForAllStates.containsKey(targetStateDesc)) {
throw new RuntimeException("Don't have state: " + targetStateDesc);
} else {
// remove from mapping
mMapForAllStates.remove(targetStateDesc);
}
// update all state
IState targetState = null;
for (IState state : mAllStates) {
if (state.getStateDesc().equals(targetStateDesc)) {
targetState = state;
} else {
state.removeTransit(targetStateDesc);
}
}
mAllStates.remove(targetState);
}
#Override
public IState getCurrentState() {
return mCurrentState;
}
#Override
public void transit(Action action) {
if (mCurrentState == null) {
throw new RuntimeException("Please setup start state");
}
Map<String, IState> localMapping = mCurrentState.getAdjacentStates();
if (localMapping.containsKey(action.toString())) {
mCurrentState = localMapping.get(action.toString());
} else {
throw new RuntimeException("No action start from current state");
}
}
#Override
public IState getStartState() {
return mStartState;
}
#Override
public IState getEndState() {
return mEndState;
}
}
example:
public class example {
public static void main(String[] args) {
System.out.println("Finite state machine!!!");
IState startState = new StateImpl("start");
IState endState = new StateImpl("end");
IFiniteStateMachine fsm = new FiniteStateMachineImpl();
fsm.setStartState(startState);
fsm.setEndState(endState);
IState middle1 = new StateImpl("middle1");
middle1.addTransit(new Action("path1"), endState);
fsm.addState(startState, middle1, new Action("path1"));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.transit(new Action(("path1")));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.addState(middle1, endState, new Action("path1-end"));
fsm.transit(new Action(("path1-end")));
System.out.println(fsm.getCurrentState().getStateDesc());
fsm.addState(endState, middle1, new Action("path1-end"));
}
}
Full example on Github
Well this is an old question but while nobody mentioned here, I will advice to check two existing frameworks before you implement you own State Machines.
One is Spring State Machine most of you are familiar with Spring framework, which allow us to use several features of Spring like dependency injection and everything else that Spring can offer.
It is really great for modelling the lifecycle of an Apparat, with states like INITIALIZING, STARTED, ERROR, RECOVERING, SHUTTINGDOWN, etc.. but I see lots of people are trying to model a Shopping Chart, a Reservation System with it, the memory footprint a Spring State Machine is relatively big to model millions of Shopping Charts or Reservations.
One other disadvantage, Spring State Machine, while has a capability to persist itself for long running processes but it does not have any mechanism to adapt to changes in these processes, if you persist a process and you have to recover it lets say 10 days later with a change occurred in your business process because of new software release / requirement, you have no built in means to deal with it.
I have several blogs, blog1 blog2, demonstrating how you can program Spring State Machine, specially model driven way, if you want to check it.
Mainly because the disadvantages I mentioned, I advice you to look another framework first, Akka FSM (Finite State Machine) which is more fitting with its low memory footprint to have millions and millions of instances and has a capability to adapt changing long running processes.
Now you can develop with Akka framework with Java but believe me because of some missing language elements, you don't want to read the produced code, Scala is a much more fitting language to develop with Akka. Now I hear you saying Scala is too complex, I can't convince my project leads to develop with Scala, to convince you all this is an option, I developed a Proof of Concept application using a Java/Scala hybrid with all Scala Akka Finite State Machine code generated from an UML model, if you want to check it out here the links to the blogs, blog3 blog4.
I hope this information would help you.
Here is a SUPER SIMPLE implementation/example of a FSM using just "if-else"s which avoids all of the above subclassing answers (taken from Using Finite State Machines for Pattern Matching in Java, where he is looking for a string which ends with "#" followed by numbers followed by "#"--see state graph here):
public static void main(String[] args) {
String s = "A1#312#";
String digits = "0123456789";
int state = 0;
for (int ind = 0; ind < s.length(); ind++) {
if (state == 0) {
if (s.charAt(ind) == '#')
state = 1;
} else {
boolean isNumber = digits.indexOf(s.charAt(ind)) != -1;
if (state == 1) {
if (isNumber)
state = 2;
else if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
} else if (state == 2) {
if (s.charAt(ind) == '#') {
state = 3;
} else if (isNumber) {
state = 2;
} else if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
} else if (state == 3) {
if (s.charAt(ind) == '#')
state = 1;
else
state = 0;
}
}
} //end for loop
if (state == 3)
System.out.println("It matches");
else
System.out.println("It does not match");
}
P.S: Does not answer your question directly, but shows you how to implement a FSM very easily in Java.
What is the difference between the Strategy pattern and the Command pattern? I am also looking for some examples in Java.
Typically the Command pattern is used to make an object out of what needs to be done -- to take an operation and its arguments and wrap them up in an object to be logged, held for undo, sent to a remote site, etc. There will tend to be a large number of distinct Command objects that pass through a given point in a system over time, and the Command objects will hold varying parameters describing the operation requested.
The Strategy pattern, on the other hand, is used to specify how something should be done, and plugs into a larger object or method to provide a specific algorithm. A Strategy for sorting might be a merge sort, might be an insertion sort, or perhaps something more complex like only using merge sort if the list is larger than some minimum size. Strategy objects are rarely subjected to the sort of mass shuffling about that Command objects are, instead often being used for configuration or tuning purposes.
Both patterns involve factoring the code and possibly parameters for individual operations out of the original class that contained them into another object to provide for independent variability. The differences are in the use cases encountered in practice and the intent behind each pattern.
Words are already given in the other answer. Here is the difference in concrete code.
public class ConcreteStrategy implements BaseStrategy {
#Override
public void execute(Object argument) {
// Work with passed-in argument.
}
}
public class ConcreteCommand implements BaseCommand {
private Object argument;
public ConcreteCommand(Object argument) {
this.argument = argument;
}
#Override
public void execute() {
// Work with own state.
}
}
Strategy - Quicksort or Mergesort [algo change]
Command - Open or Close [action change]
The main difference is , the command does some action over the object.
It may change the state of an object.
While Strategy decides how to process the object.
It encapsulates some business logic.
Strategy pattern is useful when you have multiple implementations (algorithms) for a given feature and you want to change the algorithm at runtime depending on parameter type.
One good example from HttpServlet code:
service() method will direct user's request to doGet() or doPost() or some other method depending on method type.
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
Salient features of Strategy pattern
It's a behavioural pattern
It's based on delegation
It changes guts of the object by modifying method behaviour
It's used to switch between family of algorithms
It changes the behaviour of the object at run time
Command pattern is used to enable loose coupling between Invoker and Receiver. Command, ConcreteCommand, Receiver, Invoker and Client are major components of this pattern.
Different Receivers will execute same Command through Invoker & Concrete Command but the implementation of Command will vary in each Receiver.
e.g. You have to implement "On" and "Off" functionality for TV & DVDPlayer. But TV and DVDPlayer will have different implementation for these commands.
Have a look at below posts with code examples :
Real World Example of the Strategy Pattern
Using Command Design pattern
I think a big difference here is that Strategy pattern is used when you need to shuffle between different objects that implement the same interface, but Command Pattern is used to shuffle between some objects that implement different interfaces ( as it encapsulates them into other objects called "Command Objects" ) and pass these command objects just like Strategy pattern does.