Skip to content

Commit e534dc3

Browse files
author
swaldmann
committed
Added/updated code skeleton, JUnit test and UML diagrams for State design pattern.
1 parent 84ace44 commit e534dc3

8 files changed

Lines changed: 307 additions & 42 deletions

File tree

doc/images/state_class.png

19.3 KB
Loading

doc/images/state_transitions.png

-785 Bytes
Loading

doc/plantuml/state.puml

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,67 @@
11
@startuml
22

3-
[*] --> Off
4-
Off --> On : turnOn()
3+
[*] -down-> Off
4+
Off -right-> On : turnOn()
55
On --> Off : turnOff()
6+
Washing --> On : finished()
67
On --> Washing : wash()
78
Washing --> Paused : openDoor()
89
Paused --> Washing : closeDoor()
910
Washing --> Off : turnOff()
11+
Off -left-> [*]
1012

1113
@enduml
1214

1315
@startuml
1416

15-
abstract class State {
16-
#stateName : String
17-
{abstract} turnOn() : State
18-
{abstract} turnOff() : State
19-
{abstract} wash() : State
20-
{abstract} openDoor() : State
21-
{abstract} closeDoor() : State
22-
getStateName() : String
17+
class Dishwasher {
18+
-dishwasherState : DishwasherState
19+
+turnOn() : void
20+
+turnOff() : void
21+
+wash() : void
22+
+finished() : void
23+
+openDoor() : void
24+
+closeDoor() : void
25+
+setState(dishwasherState : DishwasherState) : void
26+
+getState() : DishwasherState
2327
}
2428

25-
@enduml
29+
abstract class DishwasherState {
30+
#dishwasher : Dishwasher
31+
+turnOn() : void
32+
+turnOff() : void
33+
+wash() : void
34+
+finished() : void
35+
+openDoor() : void
36+
+closeDoor() : void
37+
{abstract} +getStateName() : String
38+
}
39+
40+
class OffState {
41+
+turnOn() : void
42+
+getStateName() : String
43+
}
44+
class OnState {
45+
+turnOff() : void
46+
+wash() : void
47+
+getStateName() : String
48+
}
49+
class WashingState {
50+
+finished() : void
51+
+openDoor() : void
52+
+turnOff() : void
53+
+getStateName() : String
54+
}
55+
class PausedState {
56+
+closeDoor() : void
57+
+getStateName() : String
58+
}
59+
60+
Dishwasher *-right- DishwasherState
61+
62+
DishwasherState <|-- OffState
63+
DishwasherState <|-- OnState
64+
DishwasherState <|-- WashingState
65+
DishwasherState <|-- PausedState
66+
67+
@enduml
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package de.doubleslash.kata.designpattern.state;
2+
3+
public class Dishwasher {
4+
5+
private DishwasherState offState = new OffState(this);
6+
// TODO: weitere Zustandsobjekte implementieren und initialisieren
7+
8+
private DishwasherState dishwasherState = getOffState();
9+
10+
public DishwasherState getOffState() {
11+
return offState;
12+
}
13+
14+
// TODO: getter-Methoden für weitere Zustandsobjekte
15+
16+
public void turnOn() {
17+
dishwasherState.turnOn();
18+
}
19+
20+
public void turnOff() {
21+
dishwasherState.turnOff();
22+
}
23+
24+
public void wash() {
25+
dishwasherState.wash();
26+
}
27+
28+
public void finished() {
29+
dishwasherState.finished();
30+
}
31+
32+
public void openDoor() {
33+
dishwasherState.openDoor();
34+
}
35+
36+
public void closeDoor() {
37+
dishwasherState.closeDoor();
38+
}
39+
40+
public void setState(DishwasherState dishwasherState) {
41+
this.dishwasherState = dishwasherState;
42+
}
43+
44+
public DishwasherState getState() {
45+
return dishwasherState;
46+
}
47+
48+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package de.doubleslash.kata.designpattern.state;
2+
3+
public abstract class DishwasherState {
4+
5+
protected Dishwasher dishwasher;
6+
7+
protected DishwasherState(Dishwasher dishwasher) {
8+
this.dishwasher = dishwasher;
9+
}
10+
11+
public void turnOn() {
12+
// Standardverhalten: keine Zustandsänderung
13+
}
14+
15+
public void turnOff() {
16+
// Standardverhalten: keine Zustandsänderung
17+
}
18+
19+
public void wash() {
20+
// Standardverhalten: keine Zustandsänderung
21+
}
22+
23+
public void finished() {
24+
// Standardverhalten: keine Zustandsänderung
25+
}
26+
27+
public void openDoor() {
28+
// Standardverhalten: keine Zustandsänderung
29+
}
30+
31+
public void closeDoor() {
32+
// Standardverhalten: keine Zustandsänderung
33+
}
34+
35+
public abstract String getStateName();
36+
37+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package de.doubleslash.kata.designpattern.state;
2+
3+
/**
4+
* Zustand "off" ("aus").
5+
*/
6+
public class OffState extends DishwasherState {
7+
8+
public OffState(Dishwasher dishwasher) {
9+
super(dishwasher);
10+
}
11+
12+
@Override
13+
public void turnOn() {
14+
// TODO: folgende Zeile auskommentieren und zum Funktionieren bringen:
15+
// dishwasher.setState(dishwasher.getOnState());
16+
}
17+
18+
// TODO: korrekten Zustandsnamen zurückgeben
19+
@Override
20+
public String getStateName() {
21+
return null;
22+
}
23+
24+
}

src/main/java/de/doubleslash/kata/designpattern/state/State.java

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package de.doubleslash.kata.designpattern.state;
2+
3+
import org.junit.Before;
4+
import org.junit.Test;
5+
6+
import static org.hamcrest.CoreMatchers.*;
7+
import static org.junit.Assert.assertThat;
8+
9+
/**
10+
* TODO: Das State Pattern ausimplementieren, so dass alle Tests erfolgreich durchlaufen.
11+
* An dieser Testklasse sollen keine Änderungen durchgeführt werden!
12+
*/
13+
public class DishwasherTest {
14+
15+
private static final String OFF = "off";
16+
private static final String ON = "on";
17+
private static final String WASHING = "washing";
18+
private static final String PAUSED = "paused";
19+
20+
private Dishwasher dishwasher;
21+
22+
@Before
23+
public void setUp() throws Exception {
24+
this.dishwasher = new Dishwasher();
25+
}
26+
27+
@Test
28+
public void testStateOfNewDishwasherIsOff() throws Exception {
29+
assertDishwasherIs(OFF);
30+
}
31+
32+
@Test
33+
public void testStateTransitionsFromStateOff() throws Exception {
34+
assertDishwasherIs(OFF);
35+
36+
// keine Zustandsänderung
37+
assertStateTransition( () -> dishwasher.turnOff(), OFF);
38+
assertStateTransition( () -> dishwasher.wash(), OFF);
39+
assertStateTransition( () -> dishwasher.finished(), OFF);
40+
assertStateTransition( () -> dishwasher.openDoor(), OFF);
41+
assertStateTransition( () -> dishwasher.closeDoor(), OFF);
42+
43+
// einschalten => an
44+
assertStateTransition( () -> dishwasher.turnOn(), ON);
45+
}
46+
47+
@Test
48+
public void testStateTransitionsFromStateOn() throws Exception {
49+
ensureDishwasherIsOn();
50+
51+
// keine Zustandsänderung
52+
assertStateTransition( () -> dishwasher.turnOn(), ON);
53+
assertStateTransition( () -> dishwasher.openDoor(), ON);
54+
assertStateTransition( () -> dishwasher.closeDoor(), ON);
55+
assertStateTransition( () -> dishwasher.finished(), ON);
56+
57+
// Spülvorgang starten => spült
58+
assertStateTransition( () -> dishwasher.wash(), WASHING);
59+
60+
// ausschalten => aus
61+
ensureDishwasherIsOn();
62+
assertStateTransition( () -> dishwasher.turnOff(), OFF);
63+
}
64+
65+
@Test
66+
public void testStateTransitionsFromStateWashing() throws Exception {
67+
ensureDishwasherIsWashing();
68+
69+
// keine Zustandsänderung
70+
assertStateTransition( () -> dishwasher.turnOn(), WASHING);
71+
assertStateTransition( () -> dishwasher.wash(), WASHING);
72+
assertStateTransition( () -> dishwasher.closeDoor(), WASHING);
73+
74+
// Spülvorgang beenden => an
75+
assertStateTransition( () -> dishwasher.finished(), ON);
76+
77+
// ausschalten => aus
78+
ensureDishwasherIsWashing();
79+
assertStateTransition( () -> dishwasher.turnOff(), OFF);
80+
81+
// Tür öffnen => Pause
82+
ensureDishwasherIsWashing();
83+
assertStateTransition( () -> dishwasher.openDoor(), PAUSED);
84+
}
85+
86+
@Test
87+
public void testStateTransitionsFromStatePaused() throws Exception {
88+
ensureDishwasherIsPaused();
89+
90+
// keine Zustandsänderung
91+
assertStateTransition( () -> dishwasher.openDoor(), PAUSED);
92+
assertStateTransition( () -> dishwasher.turnOff(), PAUSED);
93+
assertStateTransition( () -> dishwasher.wash(), PAUSED);
94+
assertStateTransition( () -> dishwasher.finished(), PAUSED);
95+
assertStateTransition( () -> dishwasher.turnOn(), PAUSED);
96+
97+
// Tür schließen => weiterspülen
98+
assertStateTransition( () -> dishwasher.closeDoor(), WASHING);
99+
}
100+
101+
private void ensureDishwasherIsPaused() {
102+
ensureDishwasherIsWashing();
103+
dishwasher.openDoor();
104+
assertDishwasherIs(PAUSED);
105+
}
106+
107+
private void ensureDishwasherIsWashing() {
108+
ensureDishwasherIsOn();
109+
dishwasher.wash();
110+
assertDishwasherIs(WASHING);
111+
}
112+
113+
private void ensureDishwasherIsOn() {
114+
dishwasher = new Dishwasher();
115+
dishwasher.turnOn();
116+
assertDishwasherIs(ON);
117+
}
118+
119+
/**
120+
* Prüft ob eine Aktion an der Spülmaschine den erwarteten Zustand zur Folge hat.
121+
*
122+
* @param action die ausgeführte Aktion (Lambda).
123+
* @param expectedState der erwartete Zustand.
124+
*/
125+
private void assertStateTransition(DishwasherAction action, String expectedState) {
126+
action.execute();
127+
assertDishwasherState(expectedState);
128+
}
129+
130+
private void assertDishwasherState(String expectedState) {
131+
assertDishwasherIs(expectedState);
132+
}
133+
134+
private void assertDishwasherIs(String expectedStateName) {
135+
DishwasherState state = dishwasher.getState();
136+
assertThat(state.getStateName(), is(equalTo(expectedStateName)));
137+
assertThat(state.getClass().getSimpleName().toLowerCase(), containsString(expectedStateName));
138+
}
139+
140+
}
141+
142+
@FunctionalInterface
143+
interface DishwasherAction {
144+
void execute();
145+
}

0 commit comments

Comments
 (0)