Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DesignPatterns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ with practical examples and best practices for using design patterns to create r
- [Command](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/command) 📝
- [Execute Around Method (EAM)](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/eam) ⭕
- [Observer](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/observer) 👀
- [State](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/state) 📜
- [Strategy](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy) 🎯
- [Template Method](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/template/method) 📋

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

record GreenLight() implements TrafficLightState {

@Override
public void change(TrafficLight trafficLight) {
trafficLight.setState(new YellowLight());
}

@Override
public void display() {
System.out.println("🟢 GO! The light is GREEN.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

record RedLight() implements TrafficLightState {

@Override
public void change(TrafficLight trafficLight) {
trafficLight.setState(new GreenLight());
}

@Override
public void display() {
System.out.println("🔴 STOP! The light is RED.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

class TrafficLight {

private TrafficLightState state;

TrafficLight() {
this.state = new RedLight();
}

void setState(TrafficLightState state) {
this.state = state;
}

void change() {
state.change(this);
}

void display() {
state.display();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

sealed interface TrafficLightState permits RedLight, YellowLight, GreenLight {

void change(TrafficLight trafficLight);

void display();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

record YellowLight() implements TrafficLightState {

@Override
public void change(TrafficLight trafficLight) {
trafficLight.setState(new RedLight());
}

@Override
public void display() {
System.out.println("🟡 Caution! The light is YELLOW.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

public class MediaPlayer {

private MediaPlayerState state;

public MediaPlayer() {
this.state = new StoppedState();
}

public void setState(MediaPlayerState state) {
this.state = state;
}

public void pressPlay() {
state.pressPlay(this);
}

public void pressPause() {
state.pressPause(this);
}

public void pressStop() {
state.pressStop(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

sealed interface MediaPlayerState permits PausedState, PlayingState, StoppedState {

void pressPlay(MediaPlayer player);

void pressPause(MediaPlayer player);

void pressStop(MediaPlayer player);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

record PausedState() implements MediaPlayerState {

@Override
public void pressPlay(MediaPlayer player) {
System.out.println("▶ Resuming music...");
player.setState(new PlayingState());
}

@Override
public void pressPause(MediaPlayer player) {
System.out.println("⏸ Already paused!");
}

@Override
public void pressStop(MediaPlayer player) {
System.out.println("⏹ Stopping music...");
player.setState(new StoppedState());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

record PlayingState() implements MediaPlayerState {

@Override
public void pressPlay(MediaPlayer player) {
System.out.println("▶ Already playing!");
}

@Override
public void pressPause(MediaPlayer player) {
System.out.println("⏸ Pausing music...");
player.setState(new PausedState());
}

@Override
public void pressStop(MediaPlayer player) {
System.out.println("⏹ Stopping music...");
player.setState(new StoppedState());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

record StoppedState() implements MediaPlayerState {

@Override
public void pressPlay(MediaPlayer player) {
System.out.println("▶ Starting music...");
player.setState(new PlayingState());
}

@Override
public void pressPause(MediaPlayer player) {
System.out.println("⏸ Can't pause! Music is stopped.");
}

@Override
public void pressStop(MediaPlayer player) {
System.out.println("⏹ Already stopped!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.flow;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import pl.mperor.lab.common.TestUtils;

import java.util.stream.Stream;

public class TrafficLightStateTest {

@Test
public void testTrafficLightStateChanges() {
var out = TestUtils.setTempSystemOut();
var trafficLight = new TrafficLight();

Stream.generate(() -> {
trafficLight.display();
trafficLight.change();
return trafficLight;
}).limit(4).count();

Assertions.assertLinesMatch("""
🔴 STOP! The light is RED.
🟢 GO! The light is GREEN.
🟡 Caution! The light is YELLOW.
🔴 STOP! The light is RED.
""".lines(), out.lines().stream());

TestUtils.resetSystemOut();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package pl.mperor.lab.java.design.pattern.behavioral.state.machine;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import pl.mperor.lab.common.TestUtils;

public class MediaPlayerStateTest {

@Test
public void shouldBehaveLikeStateMachine() {
var out = TestUtils.setTempSystemOut();

var player = new MediaPlayer();
player.pressPlay(); // Stopped -> Playing
player.pressPause(); // Playing -> Paused
player.pressPlay(); // Paused -> Playing
player.pressStop(); // Playing -> Stopped
player.pressPause(); // Invalid

Assertions.assertLinesMatch("""
▶ Starting music...
⏸ Pausing music...
▶ Resuming music...
⏹ Stopping music...
⏸ Can't pause! Music is stopped.
""".lines(), out.lines().stream());

TestUtils.resetSystemOut();
}
}