• 技术文章 >后端开发 >php教程

    PHP 设计模式系列之 specification规格模式_php实例

    2016-06-07 17:09:43原创452
    1、模式定义

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

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

    2、UML类图


    3、示例代码

    Item.php

    <?php
    namespace DesignPatterns\Behavioral\Specification;
    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 DesignPatterns\Behavioral\Specification;
    /**
    * 规格接口
    */
    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 DesignPatterns\Behavioral\Specification;
    
    /**
    * 规格抽象类
    */
    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 DesignPatterns\Behavioral\Specification;
    /**
    * 逻辑与规格(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 DesignPatterns\Behavioral\Specification;
    
    /**
    * 逻辑或规格
    */
    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 DesignPatterns\Behavioral\Specification;
    
    /**
    * 逻辑非规格
    */
    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 DesignPatterns\Behavioral\Specification;
    
    /**
    * 判断给定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 (!empty($this->maxPrice) && $item->getPrice() > $this->maxPrice) {
    return false;
    }
    if (!empty($this->minPrice) && $item->getPrice() < $this->minPrice) {
    return false;
    }
    return true;
    }
    }

    4、测试代码

    Tests/SpecificationTest.php

    <?php
    namespace DesignPatterns\Behavioral\Specification\Tests;
    use DesignPatterns\Behavioral\Specification\PriceSpecification;
    use DesignPatterns\Behavioral\Specification\Item;
    /**
    * 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));
    }
    }

    以上内容是脚本之家小编给大家分享的PHP 设计模式系列之 specification规格模式,希望本文分享能够帮助大家。

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    上一篇:PHP数组去重比较快的实现方式_php实例 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 你知道如何用PHP实现多进程吗• PHP与MySQL连接的方法总结• 求解:phpcms模板怎样转码?该怎么解决• php 之 cookie 跟 session 简单解读(笔记)• php怎的快捷知道某个函数在哪个文件用过
    1/1

    PHP中文网