|
| 1 | +--- |
| 2 | +layout: recipe |
| 3 | +title: Strategy Pattern |
| 4 | +chapter: Design Patterns |
| 5 | +--- |
| 6 | + |
| 7 | +h2. Problem |
| 8 | + |
| 9 | +You have more than one way to solve a problem but you need to choose (or even switch) between them at run time. |
| 10 | + |
| 11 | +h2. Solution |
| 12 | + |
| 13 | +Encapsulate your algorithms inside of Strategy objects. |
| 14 | + |
| 15 | +Given an unsorted list, for example, we can change the sorting algorithm under different circumstances. |
| 16 | + |
| 17 | +{% highlight coffeescript %} |
| 18 | +StringSorter = (algorithm) -> |
| 19 | + algorithm: algorithm |
| 20 | + sort: (list) -> |
| 21 | + this.algorithm list |
| 22 | + |
| 23 | +bubbleSort = (list) -> |
| 24 | + anySwaps = false |
| 25 | + swapPass = -> |
| 26 | + for r in [0..list.length-1] |
| 27 | + if list[r] > list[r+1] |
| 28 | + anySwaps = true |
| 29 | + [list[r], list[r+1]] = [list[r+1], list[r]] |
| 30 | + |
| 31 | + swapPass() |
| 32 | + while anySwaps |
| 33 | + anySwaps = false |
| 34 | + swapPass() |
| 35 | + list |
| 36 | + |
| 37 | +reverseBubbleSort = (list) -> |
| 38 | + anySwaps = false |
| 39 | + swapPass = -> |
| 40 | + for r in [list.length-1..1] |
| 41 | + if list[r] < list[r-1] |
| 42 | + anySwaps = true |
| 43 | + [list[r], list[r-1]] = [list[r-1], list[r]] |
| 44 | + |
| 45 | + swapPass() |
| 46 | + while anySwaps |
| 47 | + anySwaps = false |
| 48 | + swapPass() |
| 49 | + list |
| 50 | + |
| 51 | +sorter = new StringSorter bubbleSort |
| 52 | + |
| 53 | +unsortedList = ['e', 'b', 'd', 'c', 'x', 'a'] |
| 54 | + |
| 55 | +sorter.sort unsortedList |
| 56 | + |
| 57 | +# => ['a', 'b', 'c', 'd', 'e', 'x'] |
| 58 | + |
| 59 | +unsortedList.push 'w' |
| 60 | + |
| 61 | +# => ['a', 'b', 'c', 'd', 'e', 'x', 'w'] |
| 62 | + |
| 63 | +sorter.algorithm = reverseBubbleSort |
| 64 | + |
| 65 | +sorter.sort unsortedList |
| 66 | + |
| 67 | +# => ['a', 'b', 'c', 'd', 'e', 'w', 'x'] |
| 68 | +{% endhighlight %} |
| 69 | + |
| 70 | +h2. Discussion |
| 71 | + |
| 72 | +Like a skilled general, we must prepare to change our plans under constantly-changing circumstances. At the end of the example, we know that only the newest item in the array is out of order. We can then speed the sort up by switching to an algorithm that starts from the end of the array. |
| 73 | + |
| 74 | +h3. Exercises |
| 75 | + |
| 76 | +* Expand StringSorter into an AlwaysSortedArray class that implements all of the functionality of a regular array but which automatically sorts new items based on the method of insertion (e.g. push vs. shift). |
0 commit comments