@@ -3,14 +3,225 @@ title: Servant
33category : Behavioral
44language : en
55tag :
6- - Decoupling
6+ - Decoupling
77---
88
99## Intent
1010Servant is used for providing some behavior to a group of classes.
1111Instead of defining that behavior in each class - or when we cannot factor out
1212this behavior in the common parent class - it is defined once in the Servant.
1313
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+
14225## Class diagram
15226![ alt text] ( ./etc/servant-pattern.png " Servant ")
16227
0 commit comments