PHP design pattern series-Specification pattern (Specification) 1. Pattern Definition
Specification can be considered as an extension of the combination mode. Sometimes some conditions in a project determine the business logic, and these conditions can be extracted and combined in a certain relationship (and, or, or not) to flexibly customize the business logic. In addition, in application scenarios such as query and filtering, you can define multiple conditions and then use a combination of these conditions to process queries or filters, instead of using logical judgment statements for processing, the entire implementation logic can be simplified.
Each condition here is a specification. Multiple specifications/conditions are connected in series to form a combined specification in a logical relationship.
2. UML class diagram
3. sample code Item. php
price = $price; } /** * Get the items price * * @return int */ public function getPrice() { return $this->price; }}
SpecificationInterface. php
AbstractSpecification. php
Plus. php
Left = $ left; $ this-> right = $ right ;} /*** return the logic and evaluation of the two types ** @ param Item $ item ** @ return bool */public function isSatisfiedBy (Item $ item) {return $ this-> left-> isSatisfiedBy ($ item) & $ this-> right-> isSatisfiedBy ($ item );}}
Either. php
Left = $ left; $ this-> right = $ right ;} /*** return the logic or evaluation of the two types ** @ param Item $ item ** @ return bool */public function isSatisfiedBy (Item $ item) {return $ this-> left-> isSatisfiedBy ($ item) | $ this-> right-> isSatisfiedBy ($ item );}}
Not. php
Spec = $ spec;}/*** returns the opposite result of the type ** @ param Item $ item ** @ return bool */public function isSatisfiedBy (Item $ item) {return! $ This-> spec-> isSatisfiedBy ($ item );}}
PriceSpecification. php
MaxPrice = $ maxPrice;}/*** set the minimum value ** @ param int $ minPrice */public function setMinPrice ($ minPrice) {$ this-> minPrice = $ minPrice ;} /*** determine whether the pricing of a given Item is between the minimum and maximum values ** @ param Item $ item ** @ return bool */public function isSatisfiedBy (Item $ item) {if (! Empty ($ this-> maxPrice) & $ item-> getPrice ()> $ this-> maxPrice) {return false;} if (! Empty ($ this-> minPrice) & $ item-> getPrice () <$ this-> minPrice) {return false;} return true ;}}
4. test code Tests/SpecificationTest. php
AssertTrue ($ spec-> isSatisfiedBy ($ item); $ spec-> setMaxPrice (50); $ this-> assertFalse ($ spec-> isSatisfiedBy ($ item )); $ spec-& gt; setMaxPrice (150); $ this-& gt; assertTrue ($ spec-& gt; isSatisfiedBy ($ item); $ spec-& gt; setMinPrice (101 ); $ this-> assertFalse ($ spec-> isSatisfiedBy ($ item); $ spec-> setMinPrice (100 ); $ this-> assertTrue ($ spec-> isSatisfiedBy ($ item);} public function testNotSpecification () {$ item = new Item (100 ); $ spec = new PriceSpecification (); $ not = $ spec-> not (); $ this-> assertFalse ($ not-> isSatisfiedBy ($ item )); $ spec-& gt; setMaxPrice (50); $ this-& gt; assertTrue ($ not-& gt; isSatisfiedBy ($ item); $ spec-& gt; setMaxPrice (150 ); $ this-> assertFalse ($ not-> isSatisfiedBy ($ item); $ spec-> setMinPrice (101 ); $ this-> assertTrue ($ not-> isSatisfiedBy ($ item); $ spec-> setMinPrice (100 ); $ this-> assertFalse ($ not-> isSatisfiedBy ($ item);} public function testPlusSpecification () {$ spec1 = new PriceSpecification (); $ spec2 = new PriceSpecification (); $ plus = $ spec1-> plus ($ spec2); $ item = new Item (100); $ this-> assertTrue ($ plus-> isSatisfiedBy ($ item )); $ spec1-> setMaxPrice (150); $ spec2-> setMinPrice (50); $ this-> assertTrue ($ plus-> isSatisfiedBy ($ item )); $ spec1-> setMaxPrice (150); $ spec2-> setMinPrice (101); $ this-> assertFalse ($ plus-> isSatisfiedBy ($ item )); $ spec1-> setMaxPrice (99); $ spec2-> setMinPrice (50); $ this-> assertFalse ($ plus-> isSatisfiedBy ($ item ));} public function testEitherSpecification () {$ spec1 = new PriceSpecification (); $ spec2 = new PriceSpecification (); $ either = $ spec1-> either ($ spec2 ); $ item = new Item (100); $ this-> assertTrue ($ either-> isSatisfiedBy ($ item); $ spec1-> setMaxPrice (150 ); $ spec2-> setMaxPrice (150); $ this-> assertTrue ($ either-> isSatisfiedBy ($ item); $ spec1-> setMaxPrice (150 ); $ spec2-> setMaxPrice (0); $ this-> assertTrue ($ either-> isSatisfiedBy ($ item); $ spec1-> setMaxPrice (0 ); $ spec2-> setMaxPrice (150); $ this-> assertTrue ($ either-> isSatisfiedBy ($ item); $ spec1-> setMaxPrice (99 ); $ spec2-> setMaxPrice (99); $ this-> assertFalse ($ either-> isSatisfiedBy ($ item ));}}