emarref / spec
规范模式的实现。
v1.0.0
2020-07-03 09:54 UTC
Requires (Dev)
- phpunit/phpunit: ^9.2
This package is auto-updated.
Last update: 2024-08-29 05:55:57 UTC
README
这个库实现了规范模式,可用于任何项目。
通过将决策封装在遵循 SpecificationInterface 的类中,创建可组合的逻辑。
安装
$ composer require emarref/spec
用法
给定以下规范
<?php use Emarref\Spec\SpecificationInterface; use Emarref\Spec\LogicalSpecificationTrait; class MorningSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour < 12; } } class AfternoonSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour > 12 && $hour < 18; } } class NightSpecification implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $hour = (int) $subject->format('G'); return $hour > 17; } }
我们可以测试一个日期是否在上午
<?php $morning = new \DateTime('8am'); $isMorning = new MorningSpecification(); $isMorning->isSatisfiedBy($morning); // true
或下午
<?php $isAfternoon = new AfternoonSpecification(); $isAfternoon->isSatisfiedBy($morning); // false
我们可以将规范链在一起
<?php $night = new \DateTime('11pm'); $isMorning->or($isAfternoon)->isSatisfiedBy($morning); // true $isMorning->or($isAfternoon)->isSatisfiedBy($night); // false
链可以很深
<?php $isMorning->or($isAfternoon->andNot($isNight))->isSatisfiedBy($morning); // true
业务逻辑可以通过自定义规范进行封装。创建一个实现 Emarref\Spec\SpecificationInterface
的类。使用 Emarref\Spec\LogicalSpecificationTrait
来实现大部分模板代码。
<?php class StoreIsOpen implements SpecificationInterface { use LogicalSpecificationTrait; public function isSatisfiedBy($subject): bool { if (!$subject instanceof \DateTimeInterface) { throw new \InvalidArgumentException('Subject must be a date time object.'); } $isMorning = new MorningSpec(); $isAfternoon = new AfternoonSpec(); return $isMorning->or($isAfternoon)->isSatisfiedBy($subject); } } $storeIsOpen = new StoreIsOpen(); $storeIsOpen->isSatisfiedBy(new DateTime('10am')); // true $storeIsOpen->isSatisfiedBy(new DateTime('11pm')); // false