Skip to content

Commit a67e3c9

Browse files
committed
Added Specification Pattern
1 parent 8039eb6 commit a67e3c9

14 files changed

+333
-1
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class AgeSpecification implements Specification {
6+
7+
private int $maxAge;
8+
9+
public function __construct(int $maxAge)
10+
{
11+
$this->maxAge = $maxAge;
12+
}
13+
14+
public function isSatisfiedBy(Candidate $candidate) : bool
15+
{
16+
return $candidate->getAge() <= $this->maxAge;
17+
}
18+
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class AndSpecification implements Specification {
6+
7+
private array $specifications;
8+
9+
public function __construct(Specification ...$specifications)
10+
{
11+
$this->specifications = $specifications;
12+
}
13+
14+
public function isSatisfiedBy(Candidate $candidate): bool
15+
{
16+
foreach ($this->specifications as $specification) {
17+
if (! $specification->isSatisfiedBy($candidate)) {
18+
return false;
19+
}
20+
}
21+
22+
return true;
23+
}
24+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class Candidate
6+
{
7+
private int $age;
8+
private array $workExperience;
9+
private array $education;
10+
private bool $isConvicted;
11+
12+
public function __construct(int $age, array $workExperience, array $education, bool $isConvicted)
13+
{
14+
$this->age = $age;
15+
$this->workExperience = $workExperience;
16+
$this->education = $education;
17+
$this->isConvicted = $isConvicted;
18+
}
19+
20+
public function getAge(): int
21+
{
22+
return $this->age;
23+
}
24+
25+
public function getWorkExperience(): array
26+
{
27+
return $this->workExperience;
28+
}
29+
30+
public function getEducation()
31+
{
32+
return $this->education;
33+
}
34+
35+
public function isConvicted(): bool
36+
{
37+
return $this->isConvicted;
38+
}
39+
40+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class ConvictedSpecification implements Specification
6+
{
7+
8+
public function isSatisfiedBy(Candidate $candidate): bool
9+
{
10+
return $candidate->isConvicted();
11+
}
12+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
use DateTime;
6+
7+
class Education {
8+
9+
private string $university;
10+
private DateTime $start;
11+
private DateTime $end;
12+
13+
public function __construct(string $university, DateTime $start, DateTime $end)
14+
{
15+
$this->university = $university;
16+
$this->start = $start;
17+
$this->end = $end;
18+
}
19+
20+
public function getEndDate() : DateTime {
21+
return $this->end;
22+
}
23+
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class NotSpecification implements Specification
6+
{
7+
private Specification $specification;
8+
9+
public function __construct(Specification $specification)
10+
{
11+
$this->specification = $specification;
12+
}
13+
14+
public function isSatisfiedBy(Candidate $candidate): bool
15+
{
16+
return !$this->specification->isSatisfiedBy($candidate);
17+
}
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
class OrSpecification implements Specification {
6+
7+
private array $specifications;
8+
9+
public function __construct(Specification ...$specifications)
10+
{
11+
$this->specifications = $specifications;
12+
}
13+
14+
public function isSatisfiedBy(Candidate $candidate): bool
15+
{
16+
foreach ($this->specifications as $specification) {
17+
if ($specification->isSatisfiedBy($candidate)) {
18+
return true;
19+
}
20+
}
21+
22+
return false;
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
use DateTime;
6+
use DateInterval;
7+
8+
class RecentGraduateSpecification implements Specification
9+
{
10+
private const HYSTERESIS = 12; // months
11+
12+
public function isSatisfiedBy(Candidate $candidate): bool
13+
{
14+
$maxEndDate = (new DateTime())->sub(new DateInterval(sprintf("P%dM", self::HYSTERESIS)));
15+
16+
foreach ($candidate->getEducation() as $education) {
17+
if ($education->getEndDate() < new DateTime()
18+
&& $education->getEndDate() > $maxEndDate) {
19+
return true;
20+
}
21+
}
22+
23+
return false;
24+
}
25+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
interface Specification
6+
{
7+
public function isSatisfiedBy(Candidate $candidate) : bool;
8+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Behavioral\Specification;
4+
5+
use DateTime;
6+
7+
class StudentSpecification implements Specification {
8+
9+
public function isSatisfiedBy(Candidate $candidate) : bool
10+
{
11+
foreach ($candidate->getEducation() as $education) {
12+
if ($education->getEndDate() > new DateTime()) {
13+
return true;
14+
}
15+
}
16+
17+
return false;
18+
}
19+
}

0 commit comments

Comments
 (0)