1+ <?php
2+
3+ namespace DesignPatterns ;
4+
5+ /**
6+ * strategy pattern
7+ *
8+ * Terminology:
9+ * - Context
10+ * - Strategy
11+ * - Concrete Strategy
12+ *
13+ * Purpose:
14+ * to separate strategies and to enable fast switching between them.
15+ * also this pattern is a good alternative to inheritance (instead of having an abstract class that is extended)
16+ *
17+ * Examples:
18+ * - sorting a list of objects, one strategy by date, the other by id
19+ * - simplify unit testing: e.g. switching between file and in-memory storage
20+ *
21+ */
22+
23+ interface Comparator
24+ {
25+ /**
26+ * @abstract
27+ * @param object $a
28+ * @param object $b
29+ * @return bool
30+ */
31+ public function compare ($ a , $ b );
32+ }
33+
34+ class ObjectCollection
35+ {
36+ private $ _elements ;
37+ private $ _comparator ;
38+
39+ /**
40+ * @param array $elements
41+ */
42+ public function __construct (array $ elements = array ())
43+ {
44+ $ this ->_elements = $ elements ;
45+ }
46+
47+ /**
48+ * @return array
49+ */
50+ public function sort ()
51+ {
52+ $ callback = array ($ this ->_comparator , 'compare ' );
53+ uasort ($ this ->_elements , $ callback );
54+
55+ return $ this ->_elements ;
56+ }
57+
58+ /**
59+ * @param Comparator $comparator
60+ * @return void
61+ */
62+ public function setComparator (Comparator $ comparator )
63+ {
64+ $ this ->_comparator = $ comparator ;
65+ }
66+ }
67+
68+ class IdComparator implements Comparator
69+ {
70+ public function compare ($ a , $ b )
71+ {
72+ if ($ a ['id ' ] == $ b ['id ' ]) {
73+ return 0 ;
74+ } else {
75+ return $ a ['id ' ] < $ b ['id ' ] ? -1 : 1 ;
76+ }
77+ }
78+ }
79+
80+ class DateComparator implements Comparator
81+ {
82+ public function compare ($ a , $ b )
83+ {
84+ $ aDate = strtotime ($ a ['date ' ]);
85+ $ bDate = strtotime ($ b ['date ' ]);
86+
87+ if ($ aDate == $ bDate ) {
88+ return 0 ;
89+ } else {
90+ return $ aDate < $ bDate ? -1 : 1 ;
91+ }
92+ }
93+ }
94+
95+ $ elements = array (
96+ array (
97+ 'id ' => 2 ,
98+ 'date ' => '2011-01-01 ' ,
99+ ),
100+ array (
101+ 'id ' => 1 ,
102+ 'date ' => '2011-02-01 '
103+ )
104+ );
105+
106+ $ collection = new ObjectCollection ($ elements );
107+ $ collection ->setComparator (new IdComparator ());
108+ $ collection ->sort ();
109+
110+ $ collection ->setComparator (new DateComparator ());
111+ $ collection ->sort ();
0 commit comments