The way I describe this difference to my colleagues is that state patterns are a more decentralized implementation of many stand alone encapsulated states whereas state machines are more monolithic. The monolithic nature of state machines means that a single state will be harder to reuse in a different machine and that it is harder to break a state machine up into multiple compilation units. On the other hand this monolithic design allows far better optimization of state machines and allows many implementations to represent all transition information in one place in a table. This is especially suited for situations where the person responsible for the state machine architecture or function is not well versed in the programming language it is implemented in. Remember that many engineering and Math majors have learned about state machines but have little or no education in the programming field. It is far far easier to present these types of people with a table of transitions, actions and guards than pages and pages of state patterns.
Although the article actually was a good read I disagree with the author on several points:
- "There is no reason to use state machines anymore when you are using an object oriented programming language" this is categorically not true if you have any requirement on execution speed.
- The idea that the authors implementation is particularly short or simple or that it requires less maintenance than the boost statecharts digital camera depends on your use case and personal taste but can not be said catagorically. http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html#IntermediateTopicsADigitalCamera
Notice that switching states requires an allocation! this is going to kill speed. This could be remedied by placement allocating all states in a buffer next to each other in order to save a cache miss or two. However this would require major changes to the Authors example.
Also notice that events that are not handled cannot be inlined and optimized away like in static state machines because with the state pattern they are behind a layer of dynamic indirection. This is also a potential efficiency killer depending on your requirements.
From a maintenance standpoint it should be noted that logging unhandled events cannot be done from one central superstate with the state pattern. Also the addition of a new event type/handler function requires adding a function to all states! I don't consider that maintenance friendly.
I also prefer seeing all transitions in a table rather than looking through the inner workings of every state. The author is right that adding a state is easier but only very minimally, with boost statecharts for example I only have to add the state to the list of its parents child states, that is the only real difference.
I do use the state pattern in cases where speed is a non issue and where the hierarchy of the state machine will most likely remain flat. The author is correct that the initial implementation is usually easier with the state pattern compared to a state machine and that generally more programmers should use more state machines.
One Argument for the state pattern is that it allows the implementation of "Open Closed" state machines where a state machine can be defined in a library and then expanded on by the user, this is not possible as far as I know with mainstream state machine frameworks.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…