当前位置:首页 > PHP教程 > php应用 > 列表

PHP 设计模式系列之 specification规格模式

发布:smiling 来源: PHP粉丝网  添加日期:2021-07-05 10:50:24 浏览: 评论:0 

规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),通过本文给大家介绍PHP 设计模式系列之 specification规格模式,对specification模式相关知识感兴趣的朋友一起学习吧。

1、模式定义

规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),这里做一个简单的介绍。

规格模式(Specification)可以认为是组合模式的一种扩展。有时项目中某些条件决定了业务逻辑,这些条件就可以抽离出来以某种关系(与、或、非)进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,通过预定义多个条件,然后使用这些条件的组合来处理查询或过滤,而不是使用逻辑判断语句来处理,可以简化整个实现逻辑。

这里的每个条件就是一个规格,多个规格/条件通过串联的方式以某种逻辑关系形成一个组合式的规格。

2、UML类图

3、示例代码

Item.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3. class Item 
  4. protected $price
  5.  
  6. /** 
  7. * An item must have a price 
  8. * 
  9. * @param int $price 
  10. */ 
  11. public function __construct($price
  12. $this->price = $price
  13. /** 
  14. * Get the items price 
  15. * 
  16. * @return int 
  17. */ 
  18. public function getPrice() 
  19. return $this->price; 

SpecificationInterface.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3. /** 
  4. * 规格接口 
  5. */ 
  6. interface SpecificationInterface 
  7. /** 
  8. * 判断对象是否满足规格 
  9. * 
  10. * @param Item $item 
  11. * 
  12. * @return bool 
  13. */ 
  14. public function isSatisfiedBy(Item $item); 
  15.  
  16. /** 
  17. * 创建一个逻辑与规格(AND) 
  18. * 
  19. * @param SpecificationInterface $spec 
  20. */ 
  21. public function plus(SpecificationInterface $spec); 
  22. /** 
  23. * 创建一个逻辑或规格(OR) 
  24. * 
  25. * @param SpecificationInterface $spec 
  26. */ 
  27. public function either(SpecificationInterface $spec); 
  28.  
  29. /** 
  30. * 创建一个逻辑非规格(NOT) 
  31. */ 
  32. public function not(); 

AbstractSpecification.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3.  
  4. /** 
  5. * 规格抽象类 
  6. */ 
  7. abstract class AbstractSpecification implements SpecificationInterface 
  8. /** 
  9. * 检查给定Item是否满足所有规则 
  10. * 
  11. * @param Item $item 
  12. * 
  13. * @return bool 
  14. */ 
  15. abstract public function isSatisfiedBy(Item $item); 
  16. /** 
  17. * 创建一个新的逻辑与规格(AND) 
  18. * 
  19. * @param SpecificationInterface $spec 
  20. * 
  21. * @return SpecificationInterface 
  22. */ 
  23. public function plus(SpecificationInterface $spec
  24. return new Plus($this$spec); 
  25. /** 
  26. * 创建一个新的逻辑或组合规格(OR) 
  27. * 
  28. * @param SpecificationInterface $spec 
  29. * 
  30. * @return SpecificationInterface 
  31. */ 
  32. public function either(SpecificationInterface $spec
  33. return new Either($this$spec); 
  34. /** 
  35. * 创建一个新的逻辑非规格(NOT) 
  36. * 
  37. * @return SpecificationInterface 
  38. */ 
  39. public function not() 
  40. return new Not($this); 

Plus.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3. /** 
  4. * 逻辑与规格(AND) 
  5. */ 
  6. class Plus extends AbstractSpecification 
  7. protected $left
  8. protected $right
  9.  
  10. /** 
  11. * 在构造函数中传入两种规格 
  12. * 
  13. * @param SpecificationInterface $left 
  14. * @param SpecificationInterface $right 
  15. */ 
  16. public function __construct(SpecificationInterface $left, SpecificationInterface $right
  17. $this->left = $left
  18. $this->right = $right
  19. /** 
  20. * 返回两种规格的逻辑与评估 
  21. * 
  22. * @param Item $item 
  23. * 
  24. * @return bool 
  25. */ 
  26. public function isSatisfiedBy(Item $item
  27. return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item); 

Either.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3.  
  4. /** 
  5. * 逻辑或规格 
  6. */ 
  7. class Either extends AbstractSpecification 
  8.  
  9. protected $left
  10. protected $right
  11. /** 
  12. * 两种规格的组合 
  13. * 
  14. * @param SpecificationInterface $left 
  15. * @param SpecificationInterface $right 
  16. */ 
  17. public function __construct(SpecificationInterface $left, SpecificationInterface $right
  18. $this->left = $left
  19. $this->right = $right
  20. /** 
  21. * 返回两种规格的逻辑或评估 
  22. * 
  23. * @param Item $item 
  24. * 
  25. * @return bool 
  26. */ 
  27. public function isSatisfiedBy(Item $item
  28. return $this->left->isSatisfiedBy($item) || $this->right->isSatisfiedBy($item); 

Not.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3.  
  4. /** 
  5. * 逻辑非规格 
  6. */ 
  7. class Not extends AbstractSpecification 
  8. protected $spec
  9. /** 
  10. * 在构造函数中传入指定规格 
  11. * 
  12. * @param SpecificationInterface $spec 
  13. */ 
  14. public function __construct(SpecificationInterface $spec
  15. $this->spec = $spec
  16. /** 
  17. * 返回规格的相反结果 
  18. * 
  19. * @param Item $item 
  20. * 
  21. * @return bool 
  22. */ 
  23. public function isSatisfiedBy(Item $item
  24. return !$this->spec->isSatisfiedBy($item); 

PriceSpecification.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification; 
  3.  
  4. /** 
  5. * 判断给定Item的价格是否介于最小值和最大值之间的规格 
  6. */ 
  7. class PriceSpecification extends AbstractSpecification 
  8. protected $maxPrice
  9. protected $minPrice
  10. /** 
  11. * 设置最大值 
  12. * 
  13. * @param int $maxPrice 
  14. */ 
  15. public function setMaxPrice($maxPrice
  16. $this->maxPrice = $maxPrice
  17. /** 
  18. * 设置最小值 
  19. * 
  20. * @param int $minPrice 
  21. */ 
  22. public function setMinPrice($minPrice
  23. $this->minPrice = $minPrice
  24. /** 
  25. * 判断给定Item的定价是否在最小值和最大值之间 
  26. * 
  27. * @param Item $item 
  28. * 
  29. * @return bool 
  30. */ 
  31. public function isSatisfiedBy(Item $item
  32. if (!emptyempty($this->maxPrice) && $item->getPrice() > $this->maxPrice) { 
  33. return false; 
  34. if (!emptyempty($this->minPrice) && $item->getPrice() < $this->minPrice) { 
  35. return false; 
  36. return true; 

4、测试代码

Tests/SpecificationTest.php

  1. <?php 
  2. namespace DesignPatterns\Behavioral\Specification\Tests; 
  3. use DesignPatterns\Behavioral\Specification\PriceSpecification; 
  4. use DesignPatterns\Behavioral\Specification\Item; 
  5. /** 
  6. * SpecificationTest 用于测试规格模式 
  7. */ 
  8. class SpecificationTest extends \PHPUnit_Framework_TestCase 
  9. public function testSimpleSpecification() 
  10. $item = new Item(100); 
  11. $spec = new PriceSpecification(); 
  12. $this->assertTrue($spec->isSatisfiedBy($item)); 
  13. $spec->setMaxPrice(50); 
  14. $this->assertFalse($spec->isSatisfiedBy($item)); 
  15. $spec->setMaxPrice(150); 
  16. $this->assertTrue($spec->isSatisfiedBy($item)); 
  17. $spec->setMinPrice(101); 
  18. $this->assertFalse($spec->isSatisfiedBy($item)); 
  19. $spec->setMinPrice(100); 
  20. $this->assertTrue($spec->isSatisfiedBy($item)); 
  21. public function testNotSpecification() 
  22. $item = new Item(100); 
  23. $spec = new PriceSpecification(); 
  24. $not = $spec->not(); 
  25. $this->assertFalse($not->isSatisfiedBy($item)); 
  26. $spec->setMaxPrice(50); 
  27. $this->assertTrue($not->isSatisfiedBy($item)); 
  28. $spec->setMaxPrice(150); 
  29. $this->assertFalse($not->isSatisfiedBy($item)); 
  30. $spec->setMinPrice(101); 
  31. $this->assertTrue($not->isSatisfiedBy($item)); 
  32. $spec->setMinPrice(100); 
  33. $this->assertFalse($not->isSatisfiedBy($item)); 
  34. public function testPlusSpecification() 
  35. $spec1 = new PriceSpecification(); 
  36. $spec2 = new PriceSpecification(); 
  37. $plus = $spec1->plus($spec2); 
  38. $item = new Item(100); 
  39. $this->assertTrue($plus->isSatisfiedBy($item)); 
  40. $spec1->setMaxPrice(150); 
  41. $spec2->setMinPrice(50); 
  42. $this->assertTrue($plus->isSatisfiedBy($item)); 
  43. $spec1->setMaxPrice(150); 
  44. $spec2->setMinPrice(101); 
  45. $this->assertFalse($plus->isSatisfiedBy($item)); 
  46. $spec1->setMaxPrice(99); 
  47. $spec2->setMinPrice(50); 
  48. $this->assertFalse($plus->isSatisfiedBy($item)); 
  49. public function testEitherSpecification() 
  50. $spec1 = new PriceSpecification(); 
  51. $spec2 = new PriceSpecification(); 
  52. $either = $spec1->either($spec2); 
  53. $item = new Item(100); 
  54. $this->assertTrue($either->isSatisfiedBy($item)); 
  55. $spec1->setMaxPrice(150); 
  56. $spec2->setMaxPrice(150); 
  57. $this->assertTrue($either->isSatisfiedBy($item)); 
  58. $spec1->setMaxPrice(150); 
  59. $spec2->setMaxPrice(0); 
  60. $this->assertTrue($either->isSatisfiedBy($item)); 
  61. $spec1->setMaxPrice(0); 
  62. $spec2->setMaxPrice(150); 
  63. $this->assertTrue($either->isSatisfiedBy($item)); 
  64. $spec1->setMaxPrice(99); 
  65. $spec2->setMaxPrice(99); 
  66. $this->assertFalse($either->isSatisfiedBy($item)); 
  67. }

Tags: PHP设计模式 specification

分享到: