What is the difference between a state machine and the implementation of the state pattern?

前端 未结 6 1042
無奈伤痛
無奈伤痛 2020-12-24 05:41

I wonder if a state machine is just the state pattern at work or if there is actually a difference between those two?

I found this article with the

相关标签:
6条回答
  • 2020-12-24 06:20

    I notice a difference with state Pattern. its more handy when using it for UI. lets say i wanted to lock the state. in the state Pattern context i could create a boolean and prevent states from changing further.

    here is a Kotlin example:

         inner class StateContext : State {
    
           private var stateContext: State? = null
           private var lockState: Boolean = false
    
           fun isLockState(): Boolean {
               return lockState
           }
    
           fun setLockState(lockState: Boolean): StateContext {
               this.lockState = lockState//no further actions allowed. useful if you need to permenatley lock out the user from changing state.
               return this
           }
    
           fun getState(): State? {
               return this.stateContext
           }
    
           fun setState(state: State): StateContext {
               if (!lockState) this.stateContext = state
               return this
           }
    
           override fun doAction() {
               this.stateContext?.doAction()
           }
       }
    

    with state machine im not sure how that would be done easily.

    i really like state machine when im worried about just the state (saving enum of current state for example ) , not the actual implementation detail (changing UI buttons color , for example) . the one thing about state machine thats good, is that you can have a central place to log state changes. i saw this library for kotlin by tinder which looks interesting. but i do personally think you could change them all to do what you want, just more cleaner one way vs another.

    what is a stateMachine then ? the stateMachine cares more about "what is the next state", its highlighting transition of the states rather then its detail. It maintains a flow. Usually you create it using enums. this article helps clear it up ( and references below are taken from there to help clear up the differences) but essentially this would be a state machine:

    public enum LeaveRequestState {
    
    Submitted {
        @Override
        public LeaveRequestState nextState() {
            return Escalated;
        }
    
        @Override
        public String responsiblePerson() {
            return "Employee";
        }
    },
    Escalated {
        @Override
        public LeaveRequestState nextState() {
            return Approved;
        }
    
        @Override
        public String responsiblePerson() {
            return "Team Leader";
        }
    },
    Approved {
        @Override
        public LeaveRequestState nextState() {
            return this;
        }
    
        @Override
        public String responsiblePerson() {
            return "Department Manager";
        }
    };
    
    public abstract LeaveRequestState nextState(); 
    public abstract String responsiblePerson();
    

    }

    now you know what the next transition state is for each event. So state machine CARES greatly for transitions over actually implementation of the state:

    LeaveRequestState state = LeaveRequestState.Submitted;
    
    state = state.nextState();
    assertEquals(LeaveRequestState.Escalated, state);
    
    state = state.nextState();
    assertEquals(LeaveRequestState.Approved, state);
    
    state = state.nextState();
    assertEquals(LeaveRequestState.Approved, state);
    
    0 讨论(0)
  • 2020-12-24 06:21

    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.

    0 讨论(0)
  • 2020-12-24 06:26

    I wrote an article about the state design pattern and state machines: https://medium.com/@1gravityllc/the-super-state-design-pattern-166127ce7c9a. In the article I'm showing that their focus is different but that they are also not mutually exclusive. There's a way to combine the two to come up with a super state design pattern.

    The emphasis of the state design pattern is on encapsulation of behavior to create reusable, maintainable components (the states).

    The focus of the finite state machine is on states and their transitions (captured by the state diagram) but not on the actual behavior (that’s an implementation detail).

    The article describes how these two concepts can be combined by using a finite state machine to describe and manage the states and their transitions for an object that delegates behavior to state objects using the state design pattern.

    0 讨论(0)
  • 2020-12-24 06:29

    In case anyone still interested, here is my view:

    In state machine, the object can be in different states, but we don't really care how they behave in those states. In fact, we only care what action is applied when the object is transitioned to the next state. If you implement a state machine in Java, a state will be just an enum, or a String and there will be a Transition class with doAction() method.

    On the other hand, in state pattern, you don't really care about the transition, but how the object behave in those states. The transition is just an implementation details to make your state behaviors decoupled from each other. Each state will be a separate class, having doAction() method of its own.

    Saying state pattern makes state machine obsolete is incorrect. State pattern will be useful if the behavior of each state is important, e.g in game programming, where an object can have states like "idle", "attack", "run" and in each state you want to implement the behavior of the object.

    But for use case like ordering online products, where you don't care how the order object behaves. You only care if the order is in "added_to_cart" state, when a "payment_finished" event is published, then change it to "processing" state. In this case state is a simple enum property of the Order class, thus using state machine is much better.

    0 讨论(0)
  • 2020-12-24 06:30

    A state machine can be designed and implemented in several ways. One way is to use the state pattern described in the book by the Gang of Four. But there are other patterns to implement a state machine.

    For example, you may want to have a look at the research of Miro Samek by reading the book Practical UML statecharts in C/C++, 2nd ed. (Event-Driven Programming for Embedded Systems)

    You may also find interesting this question.

    0 讨论(0)
  • 2020-12-24 06:36

    a state machine is just the state pattern at work or if there is actually a difference between those two

    TL;DR: Imagine you need to replace a state with a differently behaving one. Then imagine you need to add a new state.

    Full Answer. There is a big difference.

    The state pattern abstracts the states and decouples them from each other. So, for example, you can easily replace one particular state with another. Yet you will not be happy rewriting all the states when it is time to add a new one and/or a new transition.

    The state machine abstracts the state diagram itself and decouples it from the transition payloads. To change a particular state, you have to fix the whole diagram. But to add a state or transition, you only need to fix the diagram.

    0 讨论(0)
提交回复
热议问题