加入收藏 | 设为首页 | 会员中心 | 我要投稿 滨州站长网 (https://www.0543zz.cn/)- CDN、边缘计算、物联网、云计算、运营!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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

发布时间:2022-07-16 10:40:03 所属栏目:PHP教程 来源:互联网
导读:规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),通过本文给大家介绍PHP 设计模式系列之 specification规格模式,对specification模式相关知识感兴趣的朋友一起学习吧。 1、模式定义 规格模式是组合模式的一种扩展,在框架性
  规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),通过本文给大家介绍PHP 设计模式系列之 specification规格模式,对specification模式相关知识感兴趣的朋友一起学习吧。
 
  1、模式定义
 
  规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),这里做一个简单的介绍。
 
  规格模式(Specification)可以认为是组合模式的一种扩展。有时项目中某些条件决定了业务逻辑,这些条件就可以抽离出来以某种关系(与、或、非)进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,通过预定义多个条件,然后使用这些条件的组合来处理查询或过滤,而不是使用逻辑判断语句来处理,可以简化整个实现逻辑。
 
  这里的每个条件就是一个规格,多个规格/条件通过串联的方式以某种逻辑关系形成一个组合式的规格。
 
  2、UML类图
 
  3、示例代码
 
  Item.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
  class Item
  {
  protected $price;
   
  /**
  * An item must have a price
  *
  * @param int $price
  */
  public function __construct($price)
  {
  $this->price = $price;
  }
  /**
  * Get the items price
  *
  * @return int
  */
  public function getPrice()
  {
  return $this->price;
  }
  }
  SpecificationInterface.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
  /**
  * 规格接口
  */
  interface SpecificationInterface
  {
  /**
  * 判断对象是否满足规格
  *
  * @param Item $item
  *
  * @return bool
  */
  public function isSatisfiedBy(Item $item);
   
  /**
  * 创建一个逻辑与规格(AND)
  *
  * @param SpecificationInterface $spec
  */
  public function plus(SpecificationInterface $spec);
  /**
  * 创建一个逻辑或规格(OR)
  *
  * @param SpecificationInterface $spec
  */
  public function either(SpecificationInterface $spec);
   
  /**
  * 创建一个逻辑非规格(NOT)
  */
  public function not();
  }
  AbstractSpecification.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
   
  /**
  * 规格抽象类
  */
  abstract class AbstractSpecification implements SpecificationInterface
  {
  /**
  * 检查给定Item是否满足所有规则
  *
  * @param Item $item
  *
  * @return bool
  */
  abstract public function isSatisfiedBy(Item $item);
  /**
  * 创建一个新的逻辑与规格(AND)
  *
  * @param SpecificationInterface $spec
  *
  * @return SpecificationInterface
  */
  public function plus(SpecificationInterface $spec)
  {
  return new Plus($this, $spec);
  }
  /**
  * 创建一个新的逻辑或组合规格(OR)
  *
  * @param SpecificationInterface $spec
  *
  * @return SpecificationInterface
  */
  public function either(SpecificationInterface $spec)
  {
  return new Either($this, $spec);
  }
  /**
  * 创建一个新的逻辑非规格(NOT)
  *
  * @return SpecificationInterface
  */
  public function not()
  {
  return new Not($this);
  }
  }
  Plus.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
  /**
  * 逻辑与规格(AND)
  */
  class Plus extends AbstractSpecification
  {
  protected $left;
  protected $right;
   
  /**
  * 在构造函数中传入两种规格
  *
  * @param SpecificationInterface $left
  * @param SpecificationInterface $right
  */
  public function __construct(SpecificationInterface $left, SpecificationInterface $right)
  {
  $this->left = $left;
  $this->right = $right;
  }
  /**
  * 返回两种规格的逻辑与评估
  *
  * @param Item $item
  *
  * @return bool
  */
  public function isSatisfiedBy(Item $item)
  {
  return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item);
  }
  }
  Either.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
   
  /**
  * 逻辑或规格
  */
  class Either extends AbstractSpecification
  {
   
  protected $left;
  protected $right;
  /**
  * 两种规格的组合
  *
  * @param SpecificationInterface $left
  * @param SpecificationInterface $right
  */
  public function __construct(SpecificationInterface $left, SpecificationInterface $right)
  {
  $this->left = $left;
  $this->right = $right;
  }
  /**
  * 返回两种规格的逻辑或评估
  *
  * @param Item $item
  *
  * @return bool
  */
  public function isSatisfiedBy(Item $item)
  {
  return $this->left->isSatisfiedBy($item) || $this->right->isSatisfiedBy($item);
  }
  }
  Not.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
   
  /**
  * 逻辑非规格
  */
  class Not extends AbstractSpecification
  {
  protected $spec;
  /**
  * 在构造函数中传入指定规格
  *
  * @param SpecificationInterface $spec
  */
  public function __construct(SpecificationInterface $spec)
  {
  $this->spec = $spec;
  }
  /**
  * 返回规格的相反结果
  *
  * @param Item $item
  *
  * @return bool
  */
  public function isSatisfiedBy(Item $item)
  {
  return !$this->spec->isSatisfiedBy($item);
  }
  }
  PriceSpecification.php
 
  <?php
  namespace DesignPatternsBehavioralSpecification;
   
  /**
  * 判断给定Item的价格是否介于最小值和最大值之间的规格
  */
  class PriceSpecification extends AbstractSpecification
  {
  protected $maxPrice;
  protected $minPrice;
  /**
  * 设置最大值
  *
  * @param int $maxPrice
  */
  public function setMaxPrice($maxPrice)
  {
  $this->maxPrice = $maxPrice;
  }
  /**
  * 设置最小值
  *
  * @param int $minPrice
  */
  public function setMinPrice($minPrice)
  {
  $this->minPrice = $minPrice;
  }
  /**
  * 判断给定Item的定价是否在最小值和最大值之间
  *
  * @param Item $item
  *
  * @return bool
  */
  public function isSatisfiedBy(Item $item)
  {
  if (!emptyempty($this->maxPrice) && $item->getPrice() > $this->maxPrice) {
  return false;
  }
  if (!emptyempty($this->minPrice) && $item->getPrice() < $this->minPrice) {
  return false;
  }
  return true;
  }
  }
  4、测试代码
 
  Tests/SpecificationTest.php
 
  <?php
  namespace DesignPatternsBehavioralSpecificationTests;
  use DesignPatternsBehavioralSpecificationPriceSpecification;
  use DesignPatternsBehavioralSpecificationItem;
  /**
  * SpecificationTest 用于测试规格模式
  */
  class SpecificationTest extends PHPUnit_Framework_TestCase
  {
  public function testSimpleSpecification()
  {
  $item = new Item(100);
  $spec = new PriceSpecification();
  $this->assertTrue($spec->isSatisfiedBy($item));
  $spec->setMaxPrice(50);
  $this->assertFalse($spec->isSatisfiedBy($item));
  $spec->setMaxPrice(150);
  $this->assertTrue($spec->isSatisfiedBy($item));
  $spec->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->setMaxPrice(50);
  $this->assertTrue($not->isSatisfiedBy($item));
  $spec->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));
  }
  }
 

(编辑:滨州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读