-
-
Notifications
You must be signed in to change notification settings - Fork 27.3k
Implemented FSM design pattern issue #203 #3116
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
Closed
Closed
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
a53c561
Implemented FSM design pattern issue #203
Wessam100 d6cc250
Implemented FSM design pattern issue #203
Wessam100 30e652b
FSM issue #203
Wessam100 60a67c2
FSM issue #203
Wessam100 7474939
Fixed test coverage issues and reorganized files to adhere to the Sin…
Wessam100 d67c77d
fixed testcases
Wessam100 69da551
Update opm.xml
Wessam100 af696cb
fixed pom.xml
Wessam100 2b57ef5
edit
Wessam100 195b40e
fixed failing check
Wessam100 323afa2
update pom.xml
Wessam100 9e87fd7
fix
Wessam100 61e92bb
fixed
Wessam100 77d4cbc
added more testcases
Wessam100 b88de19
coverage
Wessam100 d5c14be
updated tests
Wessam100 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| @startuml | ||
| package com.iluwatar.trafficlight { | ||
| class GreenLightState { | ||
| + GreenLightState() | ||
| + handleEvent(context : TrafficLightContext) | ||
| } | ||
| class RedLightState { | ||
| + RedLightState() | ||
| + handleEvent(context : TrafficLightContext) | ||
| } | ||
| class TrafficLightContext { | ||
| - currentState : TrafficLightState | ||
| + TrafficLightContext(initialState : TrafficLightState) | ||
| + getCurrentState() : TrafficLightState | ||
| + handleEvent() | ||
| + setState(newState : TrafficLightState) | ||
| } | ||
| class TrafficLightFsm { | ||
| + TrafficLightFsm() | ||
| + main(args : String[]) {static} | ||
| } | ||
| interface TrafficLightState { | ||
| + handleEvent(TrafficLightContext) {abstract} | ||
| } | ||
| class YellowLightState { | ||
| + YellowLightState() | ||
| + handleEvent(context : TrafficLightContext) | ||
| } | ||
| } | ||
| TrafficLightContext --> "-currentState" TrafficLightState | ||
| GreenLightState ..|> TrafficLightState | ||
| RedLightState ..|> TrafficLightState | ||
| YellowLightState ..|> TrafficLightState | ||
| @enduml |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <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"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>com.iluwatar</groupId> | ||
| <artifactId>java-design-patterns</artifactId> | ||
| <version>1.26.0-SNAPSHOT</version> | ||
| </parent> | ||
|
|
||
| <artifactId>FiniteStateMachine</artifactId> | ||
|
|
||
| <properties> | ||
| <maven.compiler.source>17</maven.compiler.source> | ||
| <maven.compiler.target>17</maven.compiler.target> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-api</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.mockito</groupId> | ||
| <artifactId>mockito-core</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| </project> | ||
23 changes: 23 additions & 0 deletions
23
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/GreenLightState.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * Concrete state representing the Green Light. | ||
| */ | ||
| public class GreenLightState implements TrafficLightState { | ||
|
|
||
| /** | ||
| * Handles the event for the Green Light. | ||
| * This method transitions the traffic light to the Yellow state after the Green state. | ||
| * | ||
| * @param context The traffic light context to manage the state transitions. | ||
| */ | ||
| @Override | ||
| public void handleEvent(TrafficLightContext context) { | ||
| System.out.println("Green Light: Go!"); | ||
|
Owner
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. Use a proper logger |
||
| // Transition to the Yellow light state | ||
| context.setState(new YellowLightState()); | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
14 changes: 14 additions & 0 deletions
14
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/RedLightState.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * Concrete state representing the Red Light. | ||
| */ | ||
| public class RedLightState implements TrafficLightState { | ||
| @Override | ||
| public void handleEvent(TrafficLightContext context) { | ||
| System.out.println("Red Light: Stop!"); | ||
| context.setState(new GreenLightState()); | ||
| } | ||
| } | ||
|
|
||
|
|
43 changes: 43 additions & 0 deletions
43
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightContext.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * Context class for managing the current state and transitions. | ||
| */ | ||
| public class TrafficLightContext { | ||
| private TrafficLightState currentState; | ||
|
|
||
| /** | ||
| * Initializes the context with the given initial state. | ||
| * | ||
| * @param initialState the initial state of the traffic light | ||
| */ | ||
| public TrafficLightContext(TrafficLightState initialState) { | ||
| this.currentState = initialState; | ||
| } | ||
|
|
||
| /** | ||
| * Updates the current state of the traffic light. | ||
| * | ||
| * @param newState the new state to transition to | ||
| */ | ||
| public void setState(TrafficLightState newState) { | ||
| this.currentState = newState; | ||
| } | ||
|
|
||
| /** | ||
| * Handles the current state's event and transitions to the next state. | ||
| */ | ||
| public void handleEvent() { | ||
| currentState.handleEvent(this); | ||
| } | ||
|
|
||
| /** | ||
| * Gets the current state of the traffic light. | ||
| * This can be useful for testing purposes. | ||
| */ | ||
| public TrafficLightState getCurrentState() { | ||
| return currentState; | ||
| } | ||
|
Comment on lines
+38
to
+40
Owner
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. Lombok can be used to get rid of boilerplate such as getters and setters |
||
| } | ||
|
|
||
|
|
||
27 changes: 27 additions & 0 deletions
27
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightFsm.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * Simulates a traffic light system using a Finite State Machine (FSM). | ||
| */ | ||
| public class TrafficLightFsm { | ||
|
|
||
| /** | ||
| * Runs the traffic light simulation. | ||
| * | ||
| * @param args command-line arguments (not used here) | ||
| */ | ||
| public static void main(String[] args) { | ||
| // Start with the Red light | ||
| TrafficLightContext trafficLight = new TrafficLightContext(new RedLightState()); | ||
|
|
||
| // Cycle through the traffic light states | ||
| for (int i = 0; i < 6; i++) { | ||
| trafficLight.handleEvent(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
19 changes: 19 additions & 0 deletions
19
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/TrafficLightState.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * State interface for traffic light states. | ||
| */ | ||
| public interface TrafficLightState { | ||
|
|
||
| /** | ||
| * Handles the transition to the next state based on the current state. | ||
| * | ||
| * @param context the context object that manages the traffic light's state | ||
| */ | ||
| void handleEvent(TrafficLightContext context); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
13 changes: 13 additions & 0 deletions
13
FiniteStateMachine/src/main/java/com/iluwatar/trafficlight/YellowLightState.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.iluwatar.trafficlight; | ||
|
|
||
| /** | ||
| * Concrete state representing the Yellow Light. | ||
| */ | ||
| public class YellowLightState implements TrafficLightState { | ||
| @Override | ||
| public void handleEvent(TrafficLightContext context) { | ||
| System.out.println("Yellow Light: Caution!"); | ||
| context.setState(new RedLightState()); | ||
| } | ||
| } | ||
|
|
176 changes: 176 additions & 0 deletions
176
FiniteStateMachine/src/test/java/com/iluwater/TrafficLightTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,176 @@ | ||
| package com.iluwater; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
|
||
| import com.iluwatar.trafficlight.GreenLightState; | ||
| import com.iluwatar.trafficlight.RedLightState; | ||
| import com.iluwatar.trafficlight.TrafficLightContext; | ||
| import com.iluwatar.trafficlight.TrafficLightFsm; | ||
| import com.iluwatar.trafficlight.YellowLightState; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| /** | ||
| * Test class for the Traffic Light FSM. | ||
| */ | ||
| public class TrafficLightTest { | ||
|
|
||
| private TrafficLightContext context; | ||
|
|
||
| @BeforeEach | ||
| void setUp() { | ||
| // Start with the Red Light state | ||
| context = new TrafficLightContext(new RedLightState()); | ||
| } | ||
|
|
||
| @Test | ||
| void testInitialState() { | ||
| assertTrue(context.getCurrentState() instanceof RedLightState, "Initial state should be RedLightState."); | ||
| } | ||
|
|
||
| @Test | ||
| void testRedToGreenTransition() { | ||
| context.handleEvent(); | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState, "Red Light should transition to Green Light."); | ||
| } | ||
|
|
||
| @Test | ||
| void testGreenToYellowTransition() { | ||
| context.setState(new GreenLightState()); | ||
| context.handleEvent(); | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState, "Green Light should transition to Yellow Light."); | ||
| } | ||
|
|
||
| @Test | ||
| void testYellowToRedTransition() { | ||
| context.setState(new YellowLightState()); | ||
| context.handleEvent(); | ||
| assertTrue(context.getCurrentState() instanceof RedLightState, "Yellow Light should transition to Red Light."); | ||
| } | ||
|
|
||
| @Test | ||
| void testFullCycle() { | ||
| context.handleEvent(); // Red -> Green | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
|
|
||
| context.handleEvent(); // Green -> Yellow | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Test invalid state transition | ||
| @Test | ||
| void testInvalidStateTransition() { | ||
| context.setState(new RedLightState()); | ||
| try { | ||
| // This should fail, as it doesn't make sense for Red to handle an event again. | ||
| context.handleEvent(); | ||
| } catch (IllegalStateException e) { | ||
| assertTrue(true, "Handled invalid state transition."); | ||
| } | ||
| } | ||
|
|
||
| // Test state reset | ||
| @Test | ||
| void testStateReset() { | ||
| context.setState(new YellowLightState()); | ||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
|
|
||
| context.setState(new GreenLightState()); | ||
| context.handleEvent(); // Green -> Yellow | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.setState(new RedLightState()); | ||
| context.handleEvent(); // Red -> Green | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
| } | ||
|
|
||
| // Test manually setting the state | ||
| @Test | ||
| void testManualStateSet() { | ||
| context.setState(new GreenLightState()); | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
|
|
||
| context.setState(new YellowLightState()); | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.setState(new RedLightState()); | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Additional tests for edge cases | ||
|
|
||
| // Test if state is correctly set in the middle of a cycle | ||
| @Test | ||
| void testMidCycleStateSet() { | ||
| context.handleEvent(); // Red -> Green | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
|
|
||
| // Set state manually in the middle of the cycle | ||
| context.setState(new YellowLightState()); | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Test if context properly resets after complete cycle | ||
| @Test | ||
| void testContextResetAfterFullCycle() { | ||
| context.handleEvent(); // Red -> Green | ||
| context.handleEvent(); // Green -> Yellow | ||
| context.handleEvent(); // Yellow -> Red | ||
|
|
||
| // Reset and verify again | ||
| context.setState(new GreenLightState()); | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
|
|
||
| context.handleEvent(); // Green -> Yellow | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Test if the initial state remains unchanged after multiple cycles | ||
| @Test | ||
| void testMultipleCycles() { | ||
| context.handleEvent(); // Red -> Green | ||
| context.handleEvent(); // Green -> Yellow | ||
| context.handleEvent(); // Yellow -> Red | ||
|
|
||
| // Perform another full cycle and ensure the state remains correct | ||
| context.handleEvent(); // Red -> Green | ||
| assertTrue(context.getCurrentState() instanceof GreenLightState); | ||
|
|
||
| context.handleEvent(); // Green -> Yellow | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
|
|
||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Test if state changes properly when reset in the middle of cycles | ||
| @Test | ||
| void testResetMidCycle() { | ||
| context.handleEvent(); // Red -> Green | ||
| context.setState(new YellowLightState()); // Manually set Yellow | ||
| assertTrue(context.getCurrentState() instanceof YellowLightState); | ||
| context.handleEvent(); // Yellow -> Red | ||
| assertTrue(context.getCurrentState() instanceof RedLightState); | ||
| } | ||
|
|
||
| // Test for traffic light FSM running through multiple cycles | ||
| @Test | ||
| void testTrafficLightFsmCycles() { | ||
| // Start the FSM and cycle through multiple events | ||
| TrafficLightFsm.main(new String[0]); // This will run the logic in the main function of TrafficLightFsm | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This comes from parent pom.xml and can be left out