Skip to content

Commit fc85170

Browse files
committed
Finish state pattern
1 parent 1531755 commit fc85170

File tree

7 files changed

+275
-35
lines changed

7 files changed

+275
-35
lines changed

README.md

Lines changed: 153 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
## State
44

5-
State pattern is used when you need to control the state of an object.
5+
State pattern is used when you need to control the state of an object. It will avoid to have nested many ifs and elses to control the state flow.
66

7-
For example, if we want to create a keep track of the state of a music, that follows the diagram:
7+
### Without State Design Pattern
8+
9+
If we want to create a keep track of the state of a music, that follows the diagram:
810

911
<img src="./resources/StateDiagram.png" width="800px" />
1012

@@ -20,7 +22,41 @@ public class Music {
2022
}
2123
```
2224

23-
and create a MusicState interface:
25+
where `MusicState` is an enum:
26+
27+
```java
28+
public enum MusicState {
29+
PLAY, SKIP, PAUSE, STOP;
30+
}
31+
```
32+
33+
Then we have to implement ifs and elses in a method called `setState`, like so, to control the states:
34+
35+
```java
36+
public void setState(MusicState state){
37+
if(this.state.equals(MusicState.SKIP) || this.state.equals(MusicState.STOP)){
38+
return;
39+
}
40+
41+
if(this.state.equals(MusicState.PLAY)){
42+
this.state = state;
43+
return;
44+
}
45+
46+
if(this.state.equals(MusicState.PAUSE)){
47+
if(state.equals(MusicState.STOP)){
48+
return;
49+
}else {
50+
this.state = state;
51+
return;
52+
}
53+
}
54+
55+
```
56+
57+
### With State Design Pattern
58+
59+
Let's transform our `MusicState` enum in an interface:
2460
2561
```java
2662
public interface MusicState {
@@ -37,3 +73,117 @@ public interface MusicState {
3773
}
3874
3975
```
76+
77+
and now create for each state a class that implements our interface, and each method will have a different return depending of the class. Let's take `Play` and `Pause` as examples:
78+
79+
```java
80+
public class Play implements MusicState {
81+
82+
private static Play instance = new Play();
83+
84+
public static Play getInstance() {
85+
return instance;
86+
}
87+
88+
@Override
89+
public String getState() {
90+
return "▶️";
91+
}
92+
93+
@Override
94+
public String play(Music music) {
95+
return "⚠️ Operation not allowed";
96+
}
97+
98+
@Override
99+
public String pause(Music music) {
100+
music.setState(Pause.getInstance());
101+
return "";
102+
}
103+
104+
@Override
105+
public String skip(Music music) {
106+
music.setState(Skip.getInstance());
107+
return "⏭️";
108+
}
109+
110+
@Override
111+
public String stop(Music music) {
112+
music.setState(Stop.getInstance());
113+
return "⏹️";
114+
}
115+
116+
}
117+
```
118+
119+
```java
120+
public class Pause implements MusicState {
121+
122+
private static Pause instance = new Pause();
123+
124+
public static Pause getInstance() {
125+
return instance;
126+
}
127+
128+
@Override
129+
public String getState() {
130+
return "";
131+
}
132+
133+
@Override
134+
public String play(Music music) {
135+
music.setState(Play.getInstance());
136+
return "▶️";
137+
}
138+
139+
@Override
140+
public String pause(Music music) {
141+
return "⚠️ Operation not allowed";
142+
}
143+
144+
@Override
145+
public String skip(Music music) {
146+
music.setState(Skip.getInstance());
147+
return "⏭️";
148+
}
149+
150+
@Override
151+
public String stop(Music music) {
152+
return "⚠️ Operation not allowed";
153+
154+
}
155+
156+
}
157+
158+
}
159+
160+
```
161+
162+
> Note that these classes are singletons because they don't need more than one instance to work on our code.
163+
164+
Finally, we have to update our `Music` class to implement the method to each state:
165+
166+
```java
167+
public class Music {
168+
// attributes, constructor, getters and setters were ommited for simplification
169+
170+
public String play() {
171+
return state.play(this);
172+
}
173+
174+
public String pause() {
175+
return state.pause(this);
176+
}
177+
178+
public String skip() {
179+
return state.skip(this);
180+
}
181+
182+
public String stop() {
183+
return state.stop(this);
184+
}
185+
186+
}
187+
```
188+
189+
and we're done!

src/main/java/com/language/programming/model/Music.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,26 @@ public Music(String title, String artist) {
1313
this.state = Play.getInstance();
1414
}
1515

16+
public String play() {
17+
return state.play(this);
18+
}
19+
20+
public String pause() {
21+
return state.pause(this);
22+
}
23+
24+
public String skip() {
25+
return state.skip(this);
26+
}
27+
28+
public String stop() {
29+
return state.stop(this);
30+
}
31+
32+
public void setState(MusicState state) {
33+
this.state = state;
34+
}
35+
1636
public String getTitle() {
1737
return title;
1838
}

src/main/java/com/language/programming/model/states/Pause.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,25 @@ public String getState() {
1818

1919
@Override
2020
public String play(Music music) {
21-
// TODO Auto-generated method stub
22-
return null;
21+
music.setState(Play.getInstance());
22+
return "▶️";
2323
}
2424

2525
@Override
2626
public String pause(Music music) {
27-
// TODO Auto-generated method stub
28-
return null;
27+
return "⚠️ Operation not allowed";
2928
}
3029

3130
@Override
3231
public String skip(Music music) {
33-
// TODO Auto-generated method stub
34-
return null;
32+
music.setState(Skip.getInstance());
33+
return "⏭️";
3534
}
3635

3736
@Override
3837
public String stop(Music music) {
39-
// TODO Auto-generated method stub
40-
return null;
38+
return "⚠️ Operation not allowed";
39+
4140
}
4241

4342
}

src/main/java/com/language/programming/model/states/Play.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,25 @@ public String getState() {
1818

1919
@Override
2020
public String play(Music music) {
21-
// TODO Auto-generated method stub
22-
return null;
21+
return "⚠️ Operation not allowed";
2322
}
2423

2524
@Override
2625
public String pause(Music music) {
27-
// TODO Auto-generated method stub
28-
return null;
26+
music.setState(Pause.getInstance());
27+
return "⏸";
2928
}
3029

3130
@Override
3231
public String skip(Music music) {
33-
// TODO Auto-generated method stub
34-
return null;
32+
music.setState(Skip.getInstance());
33+
return "⏭️";
3534
}
3635

3736
@Override
3837
public String stop(Music music) {
39-
// TODO Auto-generated method stub
40-
return null;
38+
music.setState(Stop.getInstance());
39+
return "⏹️";
4140
}
4241

4342
}

src/main/java/com/language/programming/model/states/Skip.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,22 @@ public String getState() {
1818

1919
@Override
2020
public String play(Music music) {
21-
// TODO Auto-generated method stub
22-
return null;
21+
return "⚠️ Operation not allowed";
2322
}
2423

2524
@Override
2625
public String pause(Music music) {
27-
// TODO Auto-generated method stub
28-
return null;
26+
return "⚠️ Operation not allowed";
2927
}
3028

3129
@Override
3230
public String skip(Music music) {
33-
// TODO Auto-generated method stub
34-
return null;
31+
return "⚠️ Operation not allowed";
3532
}
3633

3734
@Override
3835
public String stop(Music music) {
39-
// TODO Auto-generated method stub
40-
return null;
36+
return "⚠️ Operation not allowed";
4137
}
4238

4339
}

src/main/java/com/language/programming/model/states/Stop.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,22 @@ public String getState() {
1818

1919
@Override
2020
public String play(Music music) {
21-
// TODO Auto-generated method stub
22-
return null;
21+
return "⚠️ Operation not allowed";
2322
}
2423

2524
@Override
2625
public String pause(Music music) {
27-
// TODO Auto-generated method stub
28-
return null;
26+
return "⚠️ Operation not allowed";
2927
}
3028

3129
@Override
3230
public String skip(Music music) {
33-
// TODO Auto-generated method stub
34-
return null;
31+
return "⚠️ Operation not allowed";
3532
}
3633

3734
@Override
3835
public String stop(Music music) {
39-
// TODO Auto-generated method stub
40-
return null;
36+
return "⚠️ Operation not allowed";
4137
}
4238

4339
}

0 commit comments

Comments
 (0)