PHP设计模式-规格模式 Specification

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

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

// 规格接口
interface SpecificationInterface
{
    // 该方法根据给定对象是否满足这个规格来返回true 或 false。
    public function isSatisfiedBy(Item $item);

    // 创建规格的AND 和逻辑
    public function plus(SpecificationInterface $spec);

    // 创建规格的OR 或逻辑    
    public function either(SpecificationInterface $spec);

    // 创建规格的Not 非逻辑
    public function not();
}
// 规格抽象类
abstract class AbstractSpecification implements SpecificationInterface
{
    // 检查给定的item是否满足所有条件
    abstract public function isSatisfiedBy(Item $item);

    public function plus(SpecificationInterface $spec)
    {
        return new Plus($this, $spec);
    }

    public function either(SpecificationInterface $spec)
    {
        return new Either($this, $spec);
    }

    public function not()
    {
        return new Not($this);
    }
}
// 操作对象类
class Item
{
    protected $price;
    
    public function __construct($price)
    {
        $this->price = $price;
    }

    public function getPrice()
    {
        return $this->price;
    }
}

以下是Plus,Either,Not 以及PriceSpecification 四个规格实体类

class Plus extends AbstractSpecification
{
    protected $left;
    protected $right;

    // 创建两个规格的和逻辑
    public function __construct(SpecificationInterface $left, SpecificationInterface $right)
    {
        $this->left = $left;
        $this->right = $right;
    }

    // 检查规格的组合AND逻辑是否通过
    public function isSatisfiedBy(Item $item)
    {
        return $this->left->isSatisfiedBy($item) && $this->right->isSatisfiedBy($item);
    }
}
class Either extends AbstractSpecification
{
    protected $left;
    protected $right;

    // 创建一个封装了两个规格组合的新规格
    public function __construct(SpecificationInterface $left, SpecificationInterface $right)
    {
        $this->left = $left;
        $this->right = $right;
    }

    // 逻辑或是否成立
    public function isSatisfiedBy(Item $item)
    {
        return $this->left->isSatisfiedBy($item) || $this->right->isSatisfiedBy($item);
    }
}
class Not extends AbstractSpecification
{
    protected $spec;

    // 创建一个新的规格封装了另外一个规格
    public function __construct(SpecificationInterface $spec)
    {
        $this->spec = $spec;
    }

    // 返回封装规格的取反结果
    public function isSatisfiedBy(Item $item)
    {
        return !$this->spec->isSatisfiedBy($item);
    }
}
// 价格规格
class PriceSpecification extends AbstractSpecification
{
    protected $maxPrice;
    protected $minPrice;

    // 设置可选的最高价
    public function setMaxPrice($maxPrice)
    {
        $this->maxPrice = $maxPrice;
    }


    // 设置可选的最低价
    public function setMinPrice($minPrice)
    {
        $this->minPrice = $minPrice;
    }

    // 检查价格是否在最大和最小之间
    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;
    }
}
// 客户端调用示例

//创建两个价格规格
$spec1 = new PriceSpecification();
$spec2 = new PriceSpecification();

//进行或的条件组合
$either = $spec1->either($spec2); //抽象规格类中定义了either方法,返回组合后的规格

$price = 100;
$item = new Item($price);
return $either->isSatisfiedBy($item);

Leave a Reply

Your email address will not be published. Required fields are marked *