构建清晰的业务规则规范,在其中可以对对象进行检查。每个规范类有一个名为[isSatisfiedBy]的方法,根据给定对象是否满足规范返回true或false。
UML 图
Item.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; class Item { public function __construct(private float $price) { } public function getPrice(): float { return $this->price; } }
Specification.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; interface Specification { public function isSatisfiedBy(Item $item): bool; }
OrSpecification.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; class OrSpecification implements Specification { private array $specifications; public function __construct(Specification ...$specifications) { $this->specifications = $specifications; } public function isSatisfiedBy(Item $item): bool { foreach ($this->specifications as $specification) { if ($specification->isSatisfiedBy($item)) { return true; } } return false; } }
PriceSpecification.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; class PriceSpecification implements Specification { public function __construct(private ?float $minPrice, private ?float $maxPrice) { } public function isSatisfiedBy(Item $item): bool { if ($this->maxPrice !== null && $item->getPrice() > $this->maxPrice) { return false; } if ($this->minPrice !== null && $item->getPrice() < $this->minPrice) { return false; } return true; } }
AndSpecification.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; class AndSpecification implements Specification { private array $specifications; public function __construct(Specification ...$specifications) { $this->specifications = $specifications; } public function isSatisfiedBy(Item $item): bool { foreach ($this->specifications as $specification) { if (!$specification->isSatisfiedBy($item)) { return false; } } return true; } }
NotSpecification.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecification; class NotSpecification implements Specification { public function __construct(private Specification $specification) { } public function isSatisfiedBy(Item $item): bool { return !$this->specification->isSatisfiedBy($item); } }
Tests/SpecificationTest.php
<?php declare(strict_types=1); namespace DesignPatternsBehavioralSpecificationTests; use DesignPatternsBehavioralSpecificationItem; use DesignPatternsBehavioralSpecificationNotSpecification; use DesignPatternsBehavioralSpecificationOrSpecification; use DesignPatternsBehavioralSpecificationAndSpecification; use DesignPatternsBehavioralSpecificationPriceSpecification; use PHPUnitFrameworkTestCase; class SpecificationTest extends TestCase { public function testCanOr() { $spec1 = new PriceSpecification(50, 99); $spec2 = new PriceSpecification(101, 200); $orSpec = new OrSpecification($spec1, $spec2); $this->assertFalse($orSpec->isSatisfiedBy(new Item(100))); $this->assertTrue($orSpec->isSatisfiedBy(new Item(51))); $this->assertTrue($orSpec->isSatisfiedBy(new Item(150))); } public function testCanAnd() { $spec1 = new PriceSpecification(50, 100); $spec2 = new PriceSpecification(80, 200); $andSpec = new AndSpecification($spec1, $spec2); $this->assertFalse($andSpec->isSatisfiedBy(new Item(150))); $this->assertFalse($andSpec->isSatisfiedBy(new Item(1))); $this->assertFalse($andSpec->isSatisfiedBy(new Item(51))); $this->assertTrue($andSpec->isSatisfiedBy(new Item(100))); } public function testCanNot() { $spec1 = new PriceSpecification(50, 100); $notSpec = new NotSpecification($spec1); $this->assertTrue($notSpec->isSatisfiedBy(new Item(150))); $this->assertFalse($notSpec->isSatisfiedBy(new Item(50))); } }
注:单例模式可能被认为是一种“反模式”。为了获得更好的可测试性和可维护性,建议使用依赖注入。目标让应用只存在一个对象的实...
功能测试是软件测试的一个分支,旨在验证软件应用程序的功能,而不管功能是否根据需求规范运行。通过给出适当的输入值,确定输出...
前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处...
OceanBase Connector/J 结果集通过使用客户端缓存来支持可滚动性,并通过使用ROWID支持可更新性。可滚动性由于基础服务器不...