File tree Expand file tree Collapse file tree 9 files changed +384
-0
lines changed
Expand file tree Collapse file tree 9 files changed +384
-0
lines changed Original file line number Diff line number Diff line change @@ -41,6 +41,7 @@ The patterns can be structured in roughly three different categories. Please cli
4141* [ Mediator] ( Mediator ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Mediator_pattern )
4242* [ NullObject] ( NullObject ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Null_Object_pattern )
4343* [ Observer] ( Observer ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Observer_pattern )
44+ * [ Specification] ( Specification ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Specification_pattern )
4445* [ State] ( State ) [ :notebook : ] ( http://en.wikipedia.org/wiki/State_pattern )
4546* [ Strategy] ( Strategy ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Strategy_pattern )
4647* [ TemplateMethod] ( TemplateMethod ) [ :notebook : ] ( http://en.wikipedia.org/wiki/Template_method_pattern )
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * An abstract specification allows the creation of wrapped specifications
6+ */
7+ abstract class AbstractSpecification implements SpecificationInterface
8+ {
9+ /**
10+ * Checks if given item meets all criteria
11+ *
12+ * @param Item $item
13+ *
14+ * @return bool
15+ */
16+ public function isSatisfiedBy (Item $ item )
17+ {
18+ }
19+
20+ /**
21+ * Creates a new logical AND specification
22+ *
23+ * @param SpecificationInterface $spec
24+ *
25+ * @return SpecificationInterface
26+ */
27+ public function plus (SpecificationInterface $ spec )
28+ {
29+ return new Plus ($ this , $ spec );
30+ }
31+
32+ /**
33+ * Creates a new logical OR composite specification
34+ *
35+ * @param SpecificationInterface $spec
36+ *
37+ * @return SpecificationInterface
38+ */
39+ public function either (SpecificationInterface $ spec )
40+ {
41+ return new Either ($ this , $ spec );
42+ }
43+
44+ /**
45+ * Creates a new logical NOT specification
46+ *
47+ * @return SpecificationInterface
48+ */
49+ public function not ()
50+ {
51+ return new Not ($ this );
52+ }
53+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * A logical AND specification
6+ */
7+ class Either extends AbstractSpecification
8+ {
9+
10+ protected $ left ;
11+ protected $ right ;
12+
13+ /**
14+ * A composite wrapper of two specifications
15+ *
16+ * @param SpecificationInterface $left
17+ * @param SpecificationInterface $right
18+
19+ */
20+ public function __construct (SpecificationInterface $ left , SpecificationInterface $ right )
21+ {
22+ $ this ->left = $ left ;
23+ $ this ->right = $ right ;
24+ }
25+
26+ /**
27+ * Returns the evaluation of both wrapped specifications as a logical AND
28+ *
29+ * @param Item $item
30+ *
31+ * @return bool
32+ */
33+ public function isSatisfiedBy (Item $ item )
34+ {
35+ return $ this ->left ->isSatisfiedBy ($ item ) || $ this ->right ->isSatisfiedBy ($ item );
36+ }
37+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * An trivial item
6+ */
7+ class Item
8+ {
9+ protected $ price ;
10+
11+ /**
12+ * An item must have a price
13+ *
14+ * @param int $price
15+
16+ */
17+ public function __construct ($ price )
18+ {
19+ $ this ->price = $ price ;
20+ }
21+
22+ /**
23+ * Get the items price
24+ *
25+ * @return int
26+ */
27+ public function getPrice ()
28+ {
29+ return $ this ->price ;
30+ }
31+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * A logical Not specification
6+ */
7+ class Not extends AbstractSpecification
8+ {
9+
10+ protected $ spec ;
11+
12+ /**
13+ * Creates a new specification wrapping another
14+ *
15+ * @param SpecificationInterface $spec
16+
17+ */
18+ public function __construct (SpecificationInterface $ spec )
19+ {
20+ $ this ->spec = $ spec ;
21+ }
22+
23+ /**
24+ * Returns the negated result of the wrapped specification
25+ *
26+ * @param Item $item
27+ *
28+ * @return bool
29+ */
30+ public function isSatisfiedBy (Item $ item )
31+ {
32+ return !$ this ->spec ->isSatisfiedBy ($ item );
33+ }
34+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * A logical AND specification
6+ */
7+ class Plus extends AbstractSpecification
8+ {
9+
10+ protected $ left ;
11+ protected $ right ;
12+
13+ /**
14+ * Creation of a locical AND of two specifications
15+ *
16+ * @param SpecificationInterface $left
17+ * @param SpecificationInterface $right
18+
19+ */
20+ public function __construct (SpecificationInterface $ left , SpecificationInterface $ right )
21+ {
22+ $ this ->left = $ left ;
23+ $ this ->right = $ right ;
24+ }
25+
26+ /**
27+ * Checks if the composite AND of specifications passes
28+ *
29+ * @param Item $item
30+ *
31+ * @return bool
32+ */
33+ public function isSatisfiedBy (Item $ item )
34+ {
35+ return $ this ->left ->isSatisfiedBy ($ item ) && $ this ->right ->isSatisfiedBy ($ item );
36+ }
37+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * A specification to check an Item is priced between min and max
6+ */
7+ class PriceSpecification extends AbstractSpecification
8+ {
9+ protected $ maxPrice ;
10+ protected $ minPrice ;
11+
12+ /**
13+ * Sets the optional maximum price
14+ *
15+ * @param int $maxPrice
16+ */
17+ public function setMaxPrice ($ maxPrice )
18+ {
19+ $ this ->maxPrice = $ maxPrice ;
20+ }
21+
22+ /**
23+ * Sets the optional minimum price
24+ *
25+ * @param int $minPrice
26+ */
27+ public function setMinPrice ($ minPrice )
28+ {
29+ $ this ->minPrice = $ minPrice ;
30+ }
31+
32+ /**
33+ * Checks if Item price falls between bounds
34+ *
35+ * @param Item $item
36+ *
37+ * @return bool
38+ */
39+ public function isSatisfiedBy (Item $ item )
40+ {
41+ if ( !empty ($ this ->maxPrice ) && $ item ->getPrice () > $ this ->maxPrice ) {
42+ return false ;
43+ }
44+ if ( !empty ($ this ->minPrice ) && $ item ->getPrice () < $ this ->minPrice ) {
45+ return false ;
46+ }
47+
48+ return true ;
49+ }
50+ }
Original file line number Diff line number Diff line change 1+ <?php
2+ namespace DesignPatterns \Specification ;
3+
4+ /**
5+ * An interface for a specification
6+ */
7+ interface SpecificationInterface
8+ {
9+ /**
10+ * A boolean evaluation indicating if the object meets the specification
11+ *
12+ * @param Item $item
13+ *
14+ * @return bool
15+ */
16+ public function isSatisfiedBy (Item $ item );
17+
18+ /**
19+ * Creates a logical AND specification
20+ *
21+ * @param SpecificationInterface $spec
22+
23+ */
24+ public function plus (SpecificationInterface $ spec );
25+
26+ /**
27+ * Creates a logical OR specification
28+ *
29+ * @param SpecificationInterface $spec
30+
31+ */
32+ public function either (SpecificationInterface $ spec );
33+
34+ /**
35+ * Creates a logical not specification
36+ */
37+ public function not ();
38+ }
You can’t perform that action at this time.
0 commit comments