@@ -3,14 +3,225 @@ title: Servant
3
3
category : Behavioral
4
4
language : en
5
5
tag :
6
- - Decoupling
6
+ - Decoupling
7
7
---
8
8
9
9
## Intent
10
10
Servant is used for providing some behavior to a group of classes.
11
11
Instead of defining that behavior in each class - or when we cannot factor out
12
12
this behavior in the common parent class - it is defined once in the Servant.
13
13
14
+ ## Explanation
15
+
16
+ Real-world example
17
+
18
+ > King, Queen, and other royal member of palace need servant to service them for feeding,
19
+ > organizing drinks, and so on.
20
+
21
+ In plain words
22
+
23
+ > Ensures one servant object to give some specific services for a group of serviced classes.
24
+
25
+ Wikipedia says
26
+
27
+ > In software engineering, the servant pattern defines an object used to offer some functionality
28
+ > to a group of classes without defining that functionality in each of them. A Servant is a class
29
+ > whose instance (or even just class) provides methods that take care of a desired service, while
30
+ > objects for which (or with whom) the servant does something, are taken as parameters.
31
+
32
+ ** Programmatic Example**
33
+
34
+ Servant class which can give services to other royal members of palace.
35
+
36
+ ``` java
37
+ /**
38
+ * Servant.
39
+ */
40
+ public class Servant {
41
+
42
+ public String name;
43
+
44
+ /**
45
+ * Constructor.
46
+ */
47
+ public Servant (String name ) {
48
+ this . name = name;
49
+ }
50
+
51
+ public void feed (Royalty r ) {
52
+ r. getFed();
53
+ }
54
+
55
+ public void giveWine (Royalty r ) {
56
+ r. getDrink();
57
+ }
58
+
59
+ public void giveCompliments (Royalty r ) {
60
+ r. receiveCompliments();
61
+ }
62
+
63
+ /**
64
+ * Check if we will be hanged.
65
+ */
66
+ public boolean checkIfYouWillBeHanged (List<Royalty > tableGuests ) {
67
+ return tableGuests. stream(). allMatch(Royalty :: getMood);
68
+ }
69
+ }
70
+ ```
71
+
72
+ Royalty is an interface. It is implemented by King, and Queen classes to get services from servant.
73
+
74
+ ``` java
75
+ interface Royalty {
76
+
77
+ void getFed ();
78
+
79
+ void getDrink ();
80
+
81
+ void changeMood ();
82
+
83
+ void receiveCompliments ();
84
+
85
+ boolean getMood ();
86
+ }
87
+ ```
88
+ King, class is implementing Royalty interface.
89
+ ``` java
90
+ public class King implements Royalty {
91
+
92
+ private boolean isDrunk;
93
+ private boolean isHungry = true ;
94
+ private boolean isHappy;
95
+ private boolean complimentReceived;
96
+
97
+ @Override
98
+ public void getFed () {
99
+ isHungry = false ;
100
+ }
101
+
102
+ @Override
103
+ public void getDrink () {
104
+ isDrunk = true ;
105
+ }
106
+
107
+ public void receiveCompliments () {
108
+ complimentReceived = true ;
109
+ }
110
+
111
+ @Override
112
+ public void changeMood () {
113
+ if (! isHungry && isDrunk) {
114
+ isHappy = true ;
115
+ }
116
+ if (complimentReceived) {
117
+ isHappy = false ;
118
+ }
119
+ }
120
+
121
+ @Override
122
+ public boolean getMood () {
123
+ return isHappy;
124
+ }
125
+ }
126
+ ```
127
+ Queen, class is implementing Royalty interface.
128
+ ``` java
129
+ public class Queen implements Royalty {
130
+
131
+ private boolean isDrunk = true ;
132
+ private boolean isHungry;
133
+ private boolean isHappy;
134
+ private boolean isFlirty = true ;
135
+ private boolean complimentReceived;
136
+
137
+ @Override
138
+ public void getFed () {
139
+ isHungry = false ;
140
+ }
141
+
142
+ @Override
143
+ public void getDrink () {
144
+ isDrunk = true ;
145
+ }
146
+
147
+ public void receiveCompliments () {
148
+ complimentReceived = true ;
149
+ }
150
+
151
+ @Override
152
+ public void changeMood () {
153
+ if (complimentReceived && isFlirty && isDrunk && ! isHungry) {
154
+ isHappy = true ;
155
+ }
156
+ }
157
+
158
+ @Override
159
+ public boolean getMood () {
160
+ return isHappy;
161
+ }
162
+
163
+ public void setFlirtiness (boolean f ) {
164
+ this . isFlirty = f;
165
+ }
166
+
167
+ }
168
+ ```
169
+
170
+ Then in order to use:
171
+
172
+ ``` java
173
+ public class App {
174
+
175
+ private static final Servant jenkins = new Servant (" Jenkins" );
176
+ private static final Servant travis = new Servant (" Travis" );
177
+
178
+ /**
179
+ * Program entry point.
180
+ */
181
+ public static void main (String [] args ) {
182
+ scenario(jenkins, 1 );
183
+ scenario(travis, 0 );
184
+ }
185
+
186
+ /**
187
+ * Can add a List with enum Actions for variable scenarios.
188
+ */
189
+ public static void scenario (Servant servant , int compliment ) {
190
+ var k = new King ();
191
+ var q = new Queen ();
192
+
193
+ var guests = List . of(k, q);
194
+
195
+ // feed
196
+ servant. feed(k);
197
+ servant. feed(q);
198
+ // serve drinks
199
+ servant. giveWine(k);
200
+ servant. giveWine(q);
201
+ // compliment
202
+ servant. giveCompliments(guests. get(compliment));
203
+
204
+ // outcome of the night
205
+ guests. forEach(Royalty :: changeMood);
206
+
207
+ // check your luck
208
+ if (servant. checkIfYouWillBeHanged(guests)) {
209
+ LOGGER . info(" {} will live another day" , servant. name);
210
+ } else {
211
+ LOGGER . info(" Poor {}. His days are numbered" , servant. name);
212
+ }
213
+ }
214
+ }
215
+ ```
216
+
217
+ The console output
218
+
219
+ ```
220
+ Jenkins will live another day
221
+ Poor Travis. His days are numbered
222
+ ```
223
+
224
+
14
225
## Class diagram
15
226
![ alt text] ( ./etc/servant-pattern.png " Servant ")
16
227
0 commit comments