-
-
Notifications
You must be signed in to change notification settings - Fork 27k
203: Finite state machine pattern #1247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
115498b
efd1f46
9db533e
ea1180c
d725caa
127527d
3c35cdc
76b3a73
17e3e47
2424fc0
c4de5d4
5382562
ee60881
6d277bd
d59f5aa
ae15aab
c08896a
adb9bda
f9f9291
6b9506c
cc14e60
e18495f
14061d8
6e1e1aa
435e7fc
0f586a2
fb39985
eb72310
b6c54b5
ce89d74
4565b89
6d0da62
31cbbe1
a904f00
0a523ae
44849ba
4eb0d15
e81741b
0216f74
87ab3a9
ecfd38b
7b58d27
35f86a7
9dc7df8
dc69a28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,25 @@ | ||||||
--- | ||||||
layout: pattern | ||||||
title: Finite state machine | ||||||
folder: Finite-state-machine | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
permalink: /patterns/Finite-state-machine/ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
categories: Behavioral | ||||||
tags: | ||||||
- Decoupling | ||||||
--- | ||||||
|
||||||
## Intent | ||||||
It represents a mathematical model of a finite number of states and their transitions and actions, | ||||||
and is an efficient programming method within a logical unit. Make the program logic clear and easy | ||||||
to understand. | ||||||
|
||||||
|
||||||
## Applicability | ||||||
Use the Finite-state-machine pattern when | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
* There are finite state for our model or software. | ||||||
|
||||||
|
||||||
## Credits | ||||||
|
||||||
* [State Machine Design Pattern](http://community.wvu.edu/~hhammar//rts/adv%20rts/statecharts%20patterns%20papers%20and%20%20examples/paper%20on%20state%20pattern%20B31-full.pdf) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
@startuml | ||
package com.iluwatar.finite.state.machine { | ||
class App { | ||
+ App() | ||
+ main(args : String[]) {static} | ||
} | ||
class Context { | ||
- state : State | ||
+ Context(state : State) | ||
+ getState() : State | ||
+ request(event : Event) | ||
+ setState(state : State) | ||
} | ||
class CoolState { | ||
+ CoolState() | ||
- Cool() | ||
- Stop() | ||
+ handle(context : Context, event : Event) | ||
} | ||
enum Event { | ||
+ MOVING_ON_OFF {static} | ||
+ MOVING_RUN {static} | ||
+ valueOf(name : String) : Event {static} | ||
+ values() : Event[] {static} | ||
} | ||
class OffState { | ||
+ OffState() | ||
- Start() | ||
+ handle(context : Context, event : Event) | ||
} | ||
class OnState { | ||
+ OnState() | ||
- Cool() | ||
- Stop() | ||
+ handle(context : Context, event : Event) | ||
} | ||
class RunState { | ||
+ RunState() | ||
- cool_down() | ||
+ handle(context : Context, event : Event) | ||
- stop() | ||
} | ||
class StandState { | ||
+ StandState() | ||
+ handle(context : Context, event : Event) | ||
- start_running() | ||
- start_walking() | ||
} | ||
interface State { | ||
+ handle(Context, Event) {abstract} | ||
} | ||
class WalkState { | ||
+ WalkState() | ||
+ handle(context : Context, event : Event) | ||
- start_running() | ||
- stop() | ||
} | ||
} | ||
Context --> "-state" State | ||
CoolState ..|> State | ||
OffState ..|> State | ||
OnState ..|> State | ||
RunState ..|> State | ||
StandState ..|> State | ||
WalkState ..|> State | ||
@enduml |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
|
||
The MIT License | ||
Copyright © 2014-2019 Ilkka Seppälä | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
||
--> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>java-design-patterns</artifactId> | ||
<groupId>com.iluwatar</groupId> | ||
<version>1.23.0-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>finite-state-machine</artifactId> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-engine</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,52 @@ | ||||||
/* | ||||||
* The MIT License | ||||||
* Copyright © 2014-2019 Ilkka Seppälä | ||||||
* | ||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
* of this software and associated documentation files (the "Software"), to deal | ||||||
* in the Software without restriction, including without limitation the rights | ||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
* copies of the Software, and to permit persons to whom the Software is | ||||||
* furnished to do so, subject to the following conditions: | ||||||
* | ||||||
* The above copyright notice and this permission notice shall be included in | ||||||
* all copies or substantial portions of the Software. | ||||||
* | ||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
* THE SOFTWARE. | ||||||
*/ | ||||||
|
||||||
package com.iluwatar.finite.state.machine; | ||||||
|
||||||
/**. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
* This model named finite state machine model, which uses finite state machine to | ||||||
* implement one thing that pull out all the states, events and actions, and manage | ||||||
* the complex state migration logic uniformly. | ||||||
* <p></p> | ||||||
* In this demo, I create a scenario that there is a game character, who has three states. | ||||||
* States: Standing;Walking;Running | ||||||
* And also there are two events, which means you can create requests to control it. | ||||||
* Events: MOVING_ON;MOVING_OFF | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the code however I see events such as MOVING_ON_OFF and MOVING_RUN? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe these events are not the easiest to understand. How about a different system like increasing and decreasing movement? From standing to walking to running and vice versa. |
||||||
* In this demo I use state pattern to implement this FSM pattern. For the meaning of every class, | ||||||
* refer to the class's Javadoc. | ||||||
*/ | ||||||
public class App { | ||||||
/**. | ||||||
* Launcher of this demo. | ||||||
* @param args is default for main method. | ||||||
*/ | ||||||
public static void main(String[]args) { | ||||||
var initState = new StandState(); | ||||||
var context = new Context(initState); | ||||||
|
||||||
context.request(Event.MOVING_ON_OFF); | ||||||
context.request(Event.MOVING_RUN); | ||||||
context.request(Event.MOVING_ON_OFF); | ||||||
context.request(Event.MOVING_ON_OFF); | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* The MIT License | ||
* Copyright © 2014-2019 Ilkka Seppälä | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package com.iluwatar.finite.state.machine; | ||
|
||
/**. | ||
* This class is a context for the State. | ||
* It defines the State that we focus on. | ||
*/ | ||
public class Context { | ||
private State state; | ||
|
||
/**. | ||
* Constructor for Context. | ||
* @param state is state data. | ||
*/ | ||
public Context(State state) { | ||
setState(state); | ||
} | ||
|
||
/**. | ||
* getter for state. | ||
* @return state of this context. | ||
*/ | ||
public State getState() { | ||
return state; | ||
} | ||
|
||
/**. | ||
* setter for state. | ||
* @param state is a state data | ||
*/ | ||
public void setState(State state) { | ||
this.state = state; | ||
} | ||
|
||
/**. | ||
* request method for an event, then it will call handle method. | ||
* @param event is an event. | ||
*/ | ||
public void request(Event event) { | ||
state.handle(this,event); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* The MIT License | ||
* Copyright © 2014-2019 Ilkka Seppälä | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package com.iluwatar.finite.state.machine; | ||
|
||
/**. | ||
* This enum event is the event for the game character. | ||
*/ | ||
public enum Event { | ||
//Event for the game character moving or stop moving | ||
MOVING_ON_OFF, | ||
//Event for the game character run. | ||
MOVING_RUN | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* The MIT License | ||
* Copyright © 2014-2019 Ilkka Seppälä | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
package com.iluwatar.finite.state.machine; | ||
|
||
/**. | ||
* A running state for the game character. | ||
*/ | ||
public class RunState implements State { | ||
/**. | ||
* This method is a handler for event. | ||
* @param context is context data. | ||
* @param event is an event. | ||
*/ | ||
@Override | ||
public void handle(Context context, Event event) { | ||
switch (event) { | ||
case MOVING_ON_OFF: | ||
context.setState(new StandState()); | ||
stop(); | ||
break; | ||
case MOVING_RUN: | ||
context.setState(new WalkState()); | ||
cool_down(); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
/**. | ||
* A method which simulates Game character stop. | ||
*/ | ||
private void stop() { | ||
System.out.println("Stop running! Game character is standing now!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use logger for outputting. Check elsewhere too. |
||
} | ||
|
||
/**. | ||
* A method which simulates Game character change from run to walk. | ||
*/ | ||
private void cool_down() { | ||
System.out.println("Stop running! Game character is walking now!"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.