1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
|
1
00:00:00,130 --> 00:00:03,320
Now let's see how this whole thing works in practice by
2
00:00:03,320 --> 00:00:06,800
using an example. We're going to consider a program that takes as
3
00:00:06,800 --> 00:00:10,450
input a text file and produce it as output, a filtered
4
00:00:10,450 --> 00:00:14,170
file. So basically it outputs a subset of the content of
5
00:00:14,170 --> 00:00:16,928
this text file based on some filter. And we're going to have
6
00:00:16,928 --> 00:00:19,440
four different types of filters. So the first one is
7
00:00:19,440 --> 00:00:21,680
not filtering which means that the whole content of the text
8
00:00:21,680 --> 00:00:25,320
file will be produced on the output. The second filter will output
9
00:00:25,320 --> 00:00:27,990
only words that starts with t. So you'll take the text file
10
00:00:27,990 --> 00:00:30,540
and simply ignore all of the words that do not start with
11
00:00:30,540 --> 00:00:33,130
t. So in the output we'll have only those words that starts
12
00:00:33,130 --> 00:00:36,030
with letter t. The third filter will produce in the output only
13
00:00:36,030 --> 00:00:39,180
words that are longer than five characters. So all the other words
14
00:00:39,180 --> 00:00:43,740
will be simply disregarded. And finally, the four filter will produce as
15
00:00:43,740 --> 00:00:47,630
output only words in the text file that are palindromes, and in
16
00:00:47,630 --> 00:00:50,590
case you don't know what a palindrome is, a palindrome is a word
17
00:00:50,590 --> 00:00:52,700
that is the same whether you read it from left
18
00:00:52,700 --> 00:00:55,800
to right or from right to left. For example, the
19
00:00:55,800 --> 00:00:58,480
word kayak, you can read it in this direction, or
20
00:00:58,480 --> 00:01:00,740
in this direction, and it's exactly the same word. So
21
00:01:00,740 --> 00:01:03,560
let's see how this program could be implemented using a
22
00:01:03,560 --> 00:01:05,980
strategy pattern. And let's do it for real as a
23
00:01:05,980 --> 00:01:10,100
demo. What we're looking at here is the editor page
24
00:01:10,100 --> 00:01:15,520
for Eclipse, open with the strategy pattern implementation for our example.
25
00:01:15,520 --> 00:01:17,130
So what I'm going to do is that, I'm going to look at a
26
00:01:17,130 --> 00:01:20,310
different part of implementation. And you will see that, you know, despite
27
00:01:20,310 --> 00:01:23,420
the fact that it's slightly longer, it's really fairly simple, it's kind
28
00:01:23,420 --> 00:01:26,230
of a straightforward implementation of what we just saw. As I just
29
00:01:26,230 --> 00:01:29,820
said, what we are doing is basically building the strategy patterns that
30
00:01:29,820 --> 00:01:34,330
allows for changing the strategies with which we're filtering an input file.
31
00:01:34,330 --> 00:01:37,380
And we have different strategies, we'll look at those in detail, and
32
00:01:37,380 --> 00:01:41,050
we said that the three participants for this pattern are the context,
33
00:01:41,050 --> 00:01:43,650
the algorithm, which is the general interface and then the concrete
34
00:01:43,650 --> 00:01:47,270
strategies, which are the concrete implementations of this algorithm. So let's
35
00:01:47,270 --> 00:01:49,790
start by looking at the context. Which is this class here.
36
00:01:49,790 --> 00:01:52,960
And as you can see it contains a reference at the current
37
00:01:52,960 --> 00:01:56,240
strategy. We call this the check strategy, which is basically our
38
00:01:56,240 --> 00:01:59,910
filter, and when the context is created by default it sets a
39
00:01:59,910 --> 00:02:02,890
strategy to the old strategy. The old strategy is the one
40
00:02:02,890 --> 00:02:06,380
that accepts all the input, so basically it doesn't filter out anything.
41
00:02:06,380 --> 00:02:08,320
And we said that the context is the interface to the
42
00:02:08,320 --> 00:02:10,889
outside world, right? So it has to provide the outside world
43
00:02:10,889 --> 00:02:14,140
with a way of selecting the strategy, the specific algorithm to
44
00:02:14,140 --> 00:02:16,850
be used, and it does that in this case by providing
45
00:02:16,850 --> 00:02:21,360
this change strategy method. This method takes a strategy as input,
46
00:02:21,360 --> 00:02:24,930
and simply replaces the current strategy with the one specified as
47
00:02:24,930 --> 00:02:28,035
a parameter. And at this point, the context also will perform
48
00:02:28,035 --> 00:02:31,830
the filtering. The filtering is pretty straightforward, so what it does is
49
00:02:31,830 --> 00:02:34,620
that it opens a file that is passed as a parameter
50
00:02:34,620 --> 00:02:37,450
so that this the file, the input file to be filtered. And
51
00:02:37,450 --> 00:02:40,560
then it reads the file line by line and then splits
52
00:02:40,560 --> 00:02:43,620
the lines into its composing words and then for each word in
53
00:02:43,620 --> 00:02:46,480
each line, what it will do, it will basically invoke the
54
00:02:46,480 --> 00:02:50,270
check method in the current strategy, which is basically the filtering method
55
00:02:50,270 --> 00:02:53,580
and if the check method returns true, which basically means that
56
00:02:53,580 --> 00:02:57,150
the word should be printed, it prints the word. Otherwise, it'll just
57
00:02:57,150 --> 00:03:00,480
skip it. So basically the filter will return false for all the
58
00:03:00,480 --> 00:03:03,470
words that have to be filtered out. Okay? This is the basic
59
00:03:03,470 --> 00:03:06,770
way in which context works. Let's see how this is used in
60
00:03:06,770 --> 00:03:10,660
our main method. The main method simply creates the context, reads the input file
61
00:03:10,660 --> 00:03:12,910
from the arguments, and then what he does is simply as a
62
00:03:12,910 --> 00:03:16,720
demonstration, it will perform the filtering using all the different filters. So
63
00:03:16,720 --> 00:03:19,310
starting from the default one, which is the one that basically doesn't
64
00:03:19,310 --> 00:03:22,150
do any filtering that reports all words, then it will switch to the
65
00:03:22,150 --> 00:03:25,400
algorithm, that only considers the words that start with t, and
66
00:03:25,400 --> 00:03:28,880
it will do that by invoking a change strategy and passing this
67
00:03:28,880 --> 00:03:30,890
strategy as the argument, and then
68
00:03:30,890 --> 00:03:32,760
performing the actual filtering through context.
69
00:03:32,760 --> 00:03:35,040
And it will do exactly the same for the strategy that only
70
00:03:35,040 --> 00:03:37,540
prints words that are longer than five and the one that
71
00:03:37,540 --> 00:03:40,460
only prints words that are palindromes. So now let's look at the
72
00:03:40,460 --> 00:03:44,090
actual algorithm. This is the interface, the algorithm interface. And you can
73
00:03:44,090 --> 00:03:47,080
see that the only thing that the interface provides is this method,
74
00:03:47,080 --> 00:03:49,760
which is the check method, that takes a string as input and will
75
00:03:49,760 --> 00:03:52,470
return a boolean. So, basically, it's the boolean that we were seeing before.
76
00:03:52,470 --> 00:03:55,010
The one that is true for the words that have to be printed
77
00:03:55,010 --> 00:03:57,490
and false for the ones that have to be filtered out. Now, we have
78
00:03:57,490 --> 00:04:01,250
all the different implementations of the algorithm, the simplest one is the all
79
00:04:01,250 --> 00:04:05,110
algorithm, the simple return is always true, so all the words will be printed.
80
00:04:05,110 --> 00:04:08,740
The second one starts with t, and again, without looking at the details
81
00:04:08,740 --> 00:04:10,660
of implementations that don't really matter, what
82
00:04:10,660 --> 00:04:12,390
it does is basically check that
83
00:04:12,390 --> 00:04:15,111
the first character is t, and returns true in that case and
84
00:04:15,111 --> 00:04:17,720
false otherwise. Similarly, for the LongerThan5
85
00:04:17,720 --> 00:04:19,380
algorithm, also in this case, this
86
00:04:19,380 --> 00:04:23,000
will implement the check strategy interface, and the check will be performed
87
00:04:23,000 --> 00:04:25,980
by checking that the word is longer than five characters and returning
88
00:04:25,980 --> 00:04:29,440
true in that case and false otherwise. And finally the Palindrome check
89
00:04:29,440 --> 00:04:32,240
is a little more complicated, but basically it just checks whether the
90
00:04:32,240 --> 00:04:35,190
word is a Palindrome and returns true in that case. Okay, so
91
00:04:35,190 --> 00:04:37,950
as I said, it doesn't really matter too much what is the specific
92
00:04:37,950 --> 00:04:40,630
implementations of these matters. What matters is that we have
93
00:04:40,630 --> 00:04:44,150
a general interface for the algorithm and then any different concrete
94
00:04:44,150 --> 00:04:48,130
implementations of the algorithm that implement different strategies. So again,
95
00:04:48,130 --> 00:04:50,730
this allows you to change the behavior of your class without
96
00:04:50,730 --> 00:04:53,420
changing class. So we have this context class that does
97
00:04:53,420 --> 00:04:57,015
different things when the filter method in invoked, depending on what
98
00:04:57,015 --> 00:04:59,930
is the current strategy. So the behavior of the class can
99
00:04:59,930 --> 00:05:03,310
change dynamically, and it changes dynamically every time that we change
100
00:05:03,310 --> 00:05:06,300
the strategy. At this point, the way this whole thing works should
101
00:05:06,300 --> 00:05:08,430
be clear, so what we're going to do is that we're going to go to
102
00:05:08,430 --> 00:05:12,010
our console, and we're actually going to run the strategy pattern and see
103
00:05:12,010 --> 00:05:15,710
what happens. So here I have a file, it's called foo.txt. And if
104
00:05:15,710 --> 00:05:18,290
we look at the content of foo, you can see that it
105
00:05:18,290 --> 00:05:21,190
says that this is just a test to assess how well this program
106
00:05:21,190 --> 00:05:24,430
performs when used on files of text. And since it checks for
107
00:05:24,430 --> 00:05:28,560
palindromes, we will also insert one such word, level. Level is a palindrome,
108
00:05:28,560 --> 00:05:31,042
because you can read it from both sides. Okay, so let's
109
00:05:31,042 --> 00:05:33,657
see what happens when we run our code. So we're going to
110
00:05:33,657 --> 00:05:36,900
run java pattern.strategy.StrategyPattern which is
111
00:05:36,900 --> 00:05:38,550
our class, and we going to fetch
112
00:05:38,550 --> 00:05:41,460
foo.txt as an input, and let's go back to the beginning
113
00:05:41,460 --> 00:05:43,980
of the output to see what happened exactly. You can see
114
00:05:43,980 --> 00:05:48,040
here that for the default strategy, which was the old strategy,
115
00:05:48,040 --> 00:05:50,810
the whole file is printed, so every word is printed. This
116
00:05:50,810 --> 00:05:53,485
is just a test to assess and so on and so forth,
117
00:05:53,485 --> 00:05:57,290
as expected. For the filter that only prints words that
118
00:05:57,290 --> 00:06:00,230
start with t, only words that start with t are printed,
119
00:06:00,230 --> 00:06:04,180
again, as expected. Similarly, for the filter that only prints words
120
00:06:04,180 --> 00:06:06,970
that are longer than 5, and finally for the one that prints
121
00:06:06,970 --> 00:06:09,540
palindromes. And here you can see that we actually have two
122
00:06:09,540 --> 00:06:12,410
because the way in which this is implemented we'll also consider
123
00:06:12,410 --> 00:06:15,300
single letter words as palindromes because you can read them from
124
00:06:15,300 --> 00:06:18,450
both sides. But you definitely will also have level in the output.
125
00:06:18,450 --> 00:06:21,040
And in case you want to play with this code yourself, I
126
00:06:21,040 --> 00:06:24,600
have made this code and also the implementation for examples of other
127
00:06:24,600 --> 00:06:28,440
design partners available as a compressed archive. And the archive is accessible
128
00:06:28,440 --> 00:06:31,120
through a URL that is provided in the notes for the cost.
|