propósito
Construya una especificación clara de reglas comerciales, en la que cada regla se pueda verificar específicamente. Cada clase de especificación tiene un método llamado isSatisfiedBy, que determina si una regla dada cumple con la especificación y devuelve verdadero o falso.
Gráficos UML
Código
- Item.php
<?php
namespace DesignPatterns\Behavioral\Specification;
class Item
{
/**
* @var float
*/
private $price;
public function __construct(float $price)
{
$this->price = $price;
}
public function getPrice(): float
{
return $this->price;
}
}
- SpecificationInterface.php
<?php
namespace DesignPatterns\Behavioral\Specification;
interface SpecificationInterface
{
public function isSatisfiedBy(Item $item): bool;
}
- OrSpecification.php
<?php
namespace DesignPatterns\Behavioral\Specification;
class OrSpecification implements SpecificationInterface
{
/**
* @var SpecificationInterface[]
*/
private $specifications;
/**
* @param SpecificationInterface[] ...$specifications
*/
public function __construct(SpecificationInterface ...$specifications)
{
$this->specifications = $specifications;
}
/**
* 如果有一条规则符合条件,返回 true,否则返回 false
*/
public function isSatisfiedBy(Item $item): bool
{
foreach ($this->specifications as $specification) {
if ($specification->isSatisfiedBy($item)) {
return true;
}
}
return false;
}
}
- PriceSpecification.php
<?php
namespace DesignPatterns\Behavioral\Specification;
class PriceSpecification implements SpecificationInterface
{
/**
* @var float|null
*/
private $maxPrice;
/**
* @var float|null
*/
private $minPrice;
/**
* @param float $minPrice
* @param float $maxPrice
*/
public function __construct($minPrice, $maxPrice)
{
$this->minPrice = $minPrice;
$this->maxPrice = $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
namespace DesignPatterns\Behavioral\Specification;
class AndSpecification implements SpecificationInterface
{
/**
* @var SpecificationInterface[]
*/
private $specifications;
/**
* @param SpecificationInterface[] ...$specifications
*/
public function __construct(SpecificationInterface ...$specifications)
{
$this->specifications = $specifications;
}
/**
* 如果有一条规则不符合条件,返回 false,否则返回 true
*/
public function isSatisfiedBy(Item $item): bool
{
foreach ($this->specifications as $specification) {
if (!$specification->isSatisfiedBy($item)) {
return false;
}
}
return true;
}
}
- NotSpecification.php
<?php
namespace DesignPatterns\Behavioral\Specification;
class NotSpecification implements SpecificationInterface
{
/**
* @var SpecificationInterface
*/
private $specification;
public function __construct(SpecificationInterface $specification)
{
$this->specification = $specification;
}
public function isSatisfiedBy(Item $item): bool
{
return !$this->specification->isSatisfiedBy($item);
}
}
prueba
- Pruebas / SpecificationTest.php
<?php
namespace DesignPatterns\Behavioral\Specification\Tests;
use DesignPatterns\Behavioral\Specification\Item;
use DesignPatterns\Behavioral\Specification\NotSpecification;
use DesignPatterns\Behavioral\Specification\OrSpecification;
use DesignPatterns\Behavioral\Specification\AndSpecification;
use DesignPatterns\Behavioral\Specification\PriceSpecification;
use PHPUnit\Framework\TestCase;
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)));
}
}
El camino de crecimiento de PHP Internet Architect * La guía definitiva para "patrones de diseño"
Entrevista con 10 empresas, obtenga 9 ofertas, preguntas de la entrevista PHP en 2020
★ Si le gusta mi artículo y desea comunicarse y aprender con desarrolladores más experimentados, obtenga más asesoría técnica y orientación relacionada con entrevistas con grandes fábricas, bienvenido a unirse a nuestro grupo, contraseña: phpzh (número de Junyang 856460874).
El último tutorial avanzado de PHP en 2020, ¡serie completa!
Si el contenido es bueno, espero que todos te apoyen y animen a dar un like / like, y bienvenidos a comunicarnos juntos; además, si tienes alguna duda, puedes sugerir lo que quieres ver en los comentarios.