├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── demo.jpg
└── src
├── Behavioral
├── ChainOfResponsibility
│ ├── ApiMiddleware.php
│ ├── App.php
│ ├── GetMiddleware.php
│ ├── Middleware.php
│ ├── MiddlewareError.php
│ ├── Request.php
│ ├── Response.php
│ ├── index.php
│ └── server.sh
├── Command
│ ├── Client.php
│ ├── Command.php
│ ├── CreateListing.php
│ ├── DeleteListing.php
│ ├── ListingRepository.php
│ └── demo.php
├── Iterator
│ ├── Employee.php
│ ├── Team.php
│ ├── TeamIterator.php
│ └── demo.php
├── NullObject
│ ├── ArrayCache.php
│ ├── Cache.php
│ └── DummyCache.php
├── Observer
│ ├── Communicator.php
│ ├── Employee.php
│ ├── HumanResources.php
│ └── demo.php
├── Specification
│ ├── AndSpecification.php
│ ├── Candidate.php
│ ├── ConvictedSpecification.php
│ ├── Education.php
│ ├── MaxAgeSpecification.php
│ ├── NotSpecification.php
│ ├── OrSpecification.php
│ ├── RecentGraduateSpecification.php
│ ├── Specification.php
│ ├── StudentSpecification.php
│ ├── WorkExperience.php
│ ├── WorkExperienceSpecification.php
│ └── demo.php
├── State
│ ├── Angry.php
│ ├── Happy.php
│ ├── Mood.php
│ ├── Neutral.php
│ ├── Person.php
│ └── demo.php
├── Strategy
│ ├── Context.php
│ ├── JSONFormatter.php
│ ├── OutputFormatter.php
│ ├── StringFormatter.php
│ ├── XMLFormatter.php
│ └── demo.php
├── TemplateMethod
│ ├── ActionMovie.php
│ ├── ComedyMovie.php
│ ├── Movie.php
│ └── demo.php
└── Visitor
│ ├── SickLeave.php
│ ├── SickLeaveReport.php
│ ├── Student.php
│ ├── University.php
│ ├── Visitable.php
│ ├── Visitor.php
│ └── demo.php
├── Creational
├── AbstractFactory
│ ├── DeviceFactory.php
│ ├── DisplayFactory.php
│ ├── IndoorDisplay.php
│ ├── IndoorIot.php
│ ├── IndoorProduct.php
│ ├── IotFactory.php
│ ├── OutdoorDisplay.php
│ ├── OutdoorIot.php
│ ├── OutdoorProduct.php
│ └── demo.php
├── Builder
│ ├── Device.php
│ ├── DeviceBuilder.php
│ ├── Director.php
│ ├── InteractiveMirror.php
│ ├── InteractiveMirrorBuilder.php
│ └── demo.php
├── FactoryMethod
│ ├── AudioBox.php
│ ├── Box.php
│ ├── BoxFactory.php
│ ├── Factory.php
│ ├── FileItem.php
│ ├── ImgBox.php
│ ├── VideoBox.php
│ └── demo.php
├── Prototype
│ ├── Computer.php
│ ├── Device.php
│ ├── DeviceGroup.php
│ └── demo.php
└── Singleton
│ └── ActiveUser.php
└── Structural
├── Adapter
├── .env.example
├── AWSFileStorage.php
├── Client.php
├── File.php
├── FileAdapter.php
├── LocalFileStorage.php
├── assets
│ └── logo.png
├── index.php
├── server.sh
└── storage
│ └── .gitkeep
├── Bridge
├── Blurred.php
├── Content.php
├── Display.php
├── Image.php
├── Standard.php
├── Video.php
└── demo.php
├── Composite
├── Budgeted.php
├── BudgetedComposite.php
├── Department.php
├── Employee.php
└── demo.php
├── Decorator
├── Product.php
├── ProductDecorator.php
├── Shirt.php
├── SummerSale.php
├── TV.php
├── WinterSale.php
└── demo.php
├── DependencyInjection
├── Storage.php
├── User.php
├── UserStorage.php
└── UserTest.php
├── Facade
├── Image.php
└── demo.php
├── FluentInterface
├── QueryBuilder.php
└── demo.php
├── Flyweight
├── Device.php
├── DeviceStorage.php
├── DeviceType.php
├── DeviceTypeFactory.php
├── Generator.php
└── demo.php
└── Proxy
├── AuthFile.php
├── File.php
├── FileProvider.php
├── User.php
└── demo.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | .idea
3 | .env
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Jakub Kapuscik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Design Patterns
2 |
3 | This project is set of simple examples of usage of different design patterns in a real world scenarios. Each one have a short description and guideline:
4 | - [Factory Method](https://medium.com/@j.kapuscik2/getting-started-with-design-patterns-in-php-4d451ccdfb71)
5 | - [src/Creational Patterns](https://medium.com/@j.kapuscik2/src/Creational-design-patterns-in-php-db365d3245ce)
6 | - [Observer](https://medium.com/@j.kapuscik2/observer-pattern-in-php-2ba240f89fb2)
7 | - [Iterator](https://medium.com/@j.kapuscik2/iterator-pattern-in-php-b7624f6bdbcf)
8 | - [State & Strategy](https://medium.com/@j.kapuscik2/state-strategy-design-patterns-by-example-f57ebd7b6211)
9 | - [Template Method](https://medium.com/@j.kapuscik2/template-method-pattern-in-php-6116fd7e8ccc?source=friends_link&sk=ac4c483446bd5a5323c09a662bd54116)
10 | - [Flyweight](https://medium.com/swlh/flyweight-design-pattern-in-php-edcda0486fb0?source=friends_link&sk=a0fa3083d5afd7e41af8a4f7a1df05f1)
11 | - [Proxy](https://medium.com/better-programming/proxy-design-pattern-and-how-to-use-it-acd0f11e5330)
12 | - [Decorator](https://medium.com/better-programming/decorator-c04fae63dfff)
13 | - [Dependency Injection](https://medium.com/better-programming/dependency-injection-8f09a93ec995)
14 | - [Composite](https://medium.com/swlh/composite-908878748d0e)
15 | - [Adapter](https://medium.com/swlh/building-cloud-storage-application-with-adapter-design-pattern-8b0105a1bda7)
16 | - [Facade](https://medium.com/better-programming/what-is-facade-design-pattern-67cb09ce35d4)
17 | - [Bridge](https://medium.com/better-programming/what-is-bridge-design-pattern-89bfa581fbd3)
18 | - [Chain of Responsibility](https://medium.com/@j.kapuscik2/what-is-chain-of-responsibility-design-pattern-ff4d22abd124)
19 | - [Visitor](https://medium.com/@j.kapuscik2/what-is-visitor-design-pattern-8451fb75876)
20 | - [Command](https://medium.com/@j.kapuscik2/what-is-cqrs-command-design-pattern-5d400fd9f93a)
21 | - [Null Object](https://medium.com/@j.kapuscik2/what-is-null-object-design-pattern-f3b4d3d28636)
22 | - [Fluent Interface](https://medium.com/@j.kapuscik2/what-is-the-fluent-interface-design-pattern-2797645b2a2e)
23 | - [Specification](https://medium.com/@j.kapuscik2/what-is-the-specification-design-pattern-4051dd9e71c3)
24 |
25 | ### Following patterns have so far been described:
26 |
27 | #### Creational:
28 | 1. [Factory Method](/src/Creational/FactoryMethod)
29 | 2. [Abstract Factory](/src/Creational/AbstractFactory)
30 | 3. [Singleton](/src/Creational/Singleton)
31 | 4. [Builder](/src/Creational/Builder)
32 | 5. [Prototype](/src/Creational/Prototype)
33 |
34 | #### Behavioral:
35 | 1. [Iterator](src/Behavioral/Iterator)
36 | 2. [Observer](src/Behavioral/Observer)
37 | 3. [State](src/Behavioral/State)
38 | 4. [Strategy](src/Behavioral/Strategy)
39 | 5. [Template Method](src/Behavioral/TemplateMethod)
40 | 6. [Chain of Responsibility](src/Behavioral/ChainOfResponsibility)
41 | 7. [Visitor](src/Behavioral/Visitor)
42 | 8. [Command](src/Behavioral/Command)
43 | 9. [Null Object](src/Behavioral/NullObject)
44 | 10. [Specification](src/Behavioral/Specification)
45 |
46 | #### Structural:
47 | 1. [Adapter](src/Structural/Adapter)
48 | 2. [Decorator](src/Structural/Decorator)
49 | 3. [Proxy](src/Structural/Proxy)
50 | 4. [Dependency Injection](src/Structural/DependencyInjection)
51 | 5. [Facade](src/Structural/Facade)
52 | 6. [Composite](src/Structural/Composite)
53 | 7. [Bridge](src/Structural/Bridge)
54 | 8. [Flyweight](src/Structural/Flyweight)
55 | 9. [Fluent Interface](src/Structural/FluentInterface)
56 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kapusj01/design_patterns",
3 | "authors": [
4 | {
5 | "name": "Jakub Kapuscik",
6 | "email": "j.kapuscik2@gmail.com"
7 | }
8 | ],
9 | "require": {
10 | "php": "^8.2",
11 | "phpunit/phpunit": "^10.2",
12 | "symfony/dotenv": "^6.3",
13 | "aws/aws-sdk-php": "^3.275"
14 | },
15 | "autoload": {
16 | "psr-4": { "App\\": "src/" }
17 | },
18 | "require-dev": {
19 | "friendsofphp/php-cs-fixer": "^3.21"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jkapuscik2/design-patterns-php/824df7fd86743fa6aaae0cae9ed99cfa1318409a/demo.jpg
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/ApiMiddleware.php:
--------------------------------------------------------------------------------
1 | hasParam(self::API_KEY_NAME)
16 | && in_array($request->getParam(self::API_KEY_NAME), self::API_KEYS)) {
17 |
18 | return parent::process($request);
19 | } else {
20 | throw new MiddlewareError("Api key validation error");
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/App.php:
--------------------------------------------------------------------------------
1 | request = new Request($_GET, $_SERVER);
13 | $this->setMiddleware();
14 | }
15 |
16 | private function setMiddleware(): void
17 | {
18 | $this->middleware = new GetMiddleware();
19 | $this->middleware->setNext(new ApiMiddleware());
20 | }
21 |
22 | public function run(): string
23 | {
24 | if ($this->middleware->process($this->request)) {
25 | return (new Response($this->request))->handle();
26 | }
27 |
28 | return "";
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/GetMiddleware.php:
--------------------------------------------------------------------------------
1 | hasServerParam($this->methodKey)
13 | && $request->getServerParam($this->methodKey) === $this->allowedMethod) {
14 |
15 | return parent::process($request);
16 | } else {
17 | throw new MiddlewareError("Only GET requests allowed");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/Middleware.php:
--------------------------------------------------------------------------------
1 | next = $middleware;
12 |
13 | return $middleware;
14 | }
15 |
16 | public function process(Request $request): bool
17 | {
18 | if (isset($this->next)) {
19 | return $this->next->process($request);
20 | }
21 | return true;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/MiddlewareError.php:
--------------------------------------------------------------------------------
1 | params[$name];
14 | }
15 |
16 | public function getParams(): array
17 | {
18 | return $this->params;
19 | }
20 |
21 | public function hasParam(string $name): bool
22 | {
23 | return array_key_exists($name, $this->params);
24 | }
25 |
26 | public function getServerParam(string $name)
27 | {
28 | return $this->server[$name];
29 | }
30 |
31 | public function hasServerParam(string $name): bool
32 | {
33 | return array_key_exists($name, $this->server);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/Response.php:
--------------------------------------------------------------------------------
1 | self::CODE_OK,
21 | "message" => "Request proceeded correctly",
22 | "params" => $this->request->getParams()
23 | ]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/index.php:
--------------------------------------------------------------------------------
1 | run();
9 |
--------------------------------------------------------------------------------
/src/Behavioral/ChainOfResponsibility/server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | php -S localhost:8000
4 |
--------------------------------------------------------------------------------
/src/Behavioral/Command/Client.php:
--------------------------------------------------------------------------------
1 | listingRepository, $title, $content, $author);
14 | $command->handle();
15 | }
16 |
17 | public function deleteListing(string $listingUuid): void
18 | {
19 | $command = new DeleteListing($this->listingRepository, $listingUuid);
20 | $command->handle();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Behavioral/Command/Command.php:
--------------------------------------------------------------------------------
1 | title) < self::MIN_TITLE_LENGTH) {
20 | throw new LengthException(sprintf(
21 | "Title is too short. Must be at least %d characters",
22 | self::MIN_TITLE_LENGTH
23 | ));
24 | }
25 | if (mb_strlen($this->content) < self::MIN_CONTENT_LENGTH) {
26 | throw new LengthException(sprintf(
27 | "Content is too short. Must be at least %d characters",
28 | self::MIN_CONTENT_LENGTH
29 | ));
30 | }
31 | if (mb_strlen($this->author) < self::MIN_AUTHOR_LENGTH) {
32 | throw new LengthException(sprintf(
33 | "Author name is too short. Must be at least %d characters",
34 | self::MIN_AUTHOR_LENGTH
35 | ));
36 | }
37 | }
38 |
39 | public function handle(): void
40 | {
41 | $this->validate();
42 | $this->repository->create($this->title, $this->content, $this->author);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Behavioral/Command/DeleteListing.php:
--------------------------------------------------------------------------------
1 | repository->delete($this->listingUid);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Behavioral/Command/ListingRepository.php:
--------------------------------------------------------------------------------
1 | createListing(
9 | "New job listing",
10 | "This is a content of a listing",
11 | "Company"
12 | );
13 | $client->deleteListing("Unique id");
14 |
--------------------------------------------------------------------------------
/src/Behavioral/Iterator/Employee.php:
--------------------------------------------------------------------------------
1 | name;
16 | }
17 |
18 | public function getPosition(): string
19 | {
20 | return $this->position;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Behavioral/Iterator/Team.php:
--------------------------------------------------------------------------------
1 | teams = new SplObjectStorage();
18 | }
19 |
20 | public function addTeam(Team $subordinate): void
21 | {
22 | $this->teams->attach($subordinate);
23 | }
24 |
25 | public function detachTeam(Team $subordinate): void
26 | {
27 | $this->teams->detach($subordinate);
28 | }
29 |
30 | public function getTeams(): SplObjectStorage
31 | {
32 | return $this->teams;
33 | }
34 |
35 | public function getIterator(): TeamIterator
36 | {
37 | return new TeamIterator($this);
38 | }
39 |
40 | public function count(): int
41 | {
42 | return count(new TeamIterator($this));
43 | }
44 |
45 | public function getName(): string
46 | {
47 | return $this->name;
48 | }
49 |
50 | public function getLeader(): Employee
51 | {
52 | return $this->leader;
53 | }
54 |
55 | public function printSummary(): void
56 | {
57 | echo $this->leader->getPosition() . ": " . $this->leader->getName() . " manages " . count($this) . " teams" . PHP_EOL;
58 |
59 | foreach ($this as $team) {
60 | echo $team->getName() . " led by: " . $team->getLeader()->getName() . PHP_EOL;
61 | }
62 | echo PHP_EOL;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Behavioral/Iterator/TeamIterator.php:
--------------------------------------------------------------------------------
1 | addTeam($employee);
16 | $this->position = 0;
17 | }
18 |
19 | protected function addTeam(Team $employee): void
20 | {
21 | foreach ($employee->getTeams() as $member) {
22 | $this->teams[] = $member;
23 | $this->addTeam($member);
24 | }
25 | }
26 |
27 | public function current(): Team
28 | {
29 | return $this->teams[$this->position];
30 | }
31 |
32 | public function next(): void
33 | {
34 | ++$this->position;
35 | }
36 |
37 | public function key(): int
38 | {
39 | return $this->position;
40 | }
41 |
42 | public function valid(): bool
43 | {
44 | return isset($this->teams[$this->position]);
45 | }
46 |
47 | public function rewind(): void
48 | {
49 | $this->position = 0;
50 | }
51 |
52 | public function count(): int
53 | {
54 | return count($this->teams);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Behavioral/Iterator/demo.php:
--------------------------------------------------------------------------------
1 | addTeam($teamA);
13 | $tech->addTeam($teamB);
14 | $ceo->addTeam($tech);
15 |
16 | $ceo->printSummary();
17 |
18 | $teamC = new Team("Team C", new Employee("Jan", 'Team Leader'));
19 | $tech->addTeam($teamC);
20 |
21 | $ceo->printSummary();
22 |
23 | $ceo->detachTeam($teamC);
24 | $tech->printSummary();
25 |
--------------------------------------------------------------------------------
/src/Behavioral/NullObject/ArrayCache.php:
--------------------------------------------------------------------------------
1 | has($key)) {
12 | return $this->data[$key];
13 | }
14 | return false;
15 | }
16 |
17 | public function set(string $key, string $data): void
18 | {
19 | $this->data[$key] = $data;
20 | }
21 |
22 | public function has(string $key): bool
23 | {
24 | return array_key_exists($key, $this->data);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Behavioral/NullObject/Cache.php:
--------------------------------------------------------------------------------
1 | employees = new SplObjectStorage();
16 | }
17 |
18 | public function attach(SplObserver $employee): void
19 | {
20 | $this->employees->attach($employee);
21 | }
22 |
23 | public function detach(SplObserver $employee): void
24 | {
25 | $this->employees->detach($employee);
26 | }
27 |
28 | public function inform(string $message): void
29 | {
30 | $this->notify($message);
31 | }
32 |
33 | public function notify(string $message = ""): void
34 | {
35 | foreach ($this->employees as $employee) {
36 | /**
37 | * @var $employee Employee
38 | */
39 | $employee->update($this, $message);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Behavioral/Observer/Employee.php:
--------------------------------------------------------------------------------
1 | sendEmail($message);
17 | }
18 |
19 | protected function sendEmail(string $message): void
20 | {
21 | echo "Sending email to: " . $this->email . " - Hello " . $this->name . ", " . $message . PHP_EOL;
22 | }
23 |
24 | public function getName(): string
25 | {
26 | return $this->name;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Behavioral/Observer/HumanResources.php:
--------------------------------------------------------------------------------
1 | communicator = new Communicator();
12 |
13 | foreach ($employees as $employee) {
14 | $this->communicator->attach($employee);
15 | }
16 | }
17 |
18 | public function inform(string $message): void
19 | {
20 | $this->communicator->inform($message);
21 | }
22 |
23 | public function layOf(Employee $employee): void
24 | {
25 | $this->communicator->detach($employee);
26 | }
27 |
28 | public function employ(Employee $employee): void
29 | {
30 | $this->communicator->attach($employee);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Behavioral/Observer/demo.php:
--------------------------------------------------------------------------------
1 | inform("Some important news");
15 |
16 | $software = new Employee("Ben", "ben@gmail.com");
17 | $hr->inform("New employee: " . $software->getName());
18 | $hr->employ($software);
19 |
20 | $hr->layOf($software);
21 | $hr->inform("Employee was laid off: " . $software->getName());
22 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/AndSpecification.php:
--------------------------------------------------------------------------------
1 | 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 | }
25 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/Candidate.php:
--------------------------------------------------------------------------------
1 | age;
14 | }
15 |
16 | public function getWorkExperience(): array
17 | {
18 | return $this->workExperience;
19 | }
20 |
21 | public function getEducation(): array
22 | {
23 | return $this->education;
24 | }
25 |
26 | public function isConvicted(): bool
27 | {
28 | return $this->isConvicted;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/ConvictedSpecification.php:
--------------------------------------------------------------------------------
1 | isConvicted();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/Education.php:
--------------------------------------------------------------------------------
1 | end;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/MaxAgeSpecification.php:
--------------------------------------------------------------------------------
1 | getAge() <= $this->maxAge;
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/NotSpecification.php:
--------------------------------------------------------------------------------
1 | specification->isSatisfiedBy($candidate);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/OrSpecification.php:
--------------------------------------------------------------------------------
1 | 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 | }
25 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/RecentGraduateSpecification.php:
--------------------------------------------------------------------------------
1 | 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 | }
26 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/Specification.php:
--------------------------------------------------------------------------------
1 | getEducation() as $education) {
12 | if ($education->getEndDate() > new DateTime()) {
13 | return true;
14 | }
15 | }
16 |
17 | return false;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/WorkExperience.php:
--------------------------------------------------------------------------------
1 | start->diff($this->end);
16 | return ($workedInterval->y * 12) + $workedInterval->m;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/WorkExperienceSpecification.php:
--------------------------------------------------------------------------------
1 | getWorkExperience() as $experience) {
16 | $totalMonthsOfExperience += $experience->getWorkedMonths();
17 | }
18 |
19 | return $totalMonthsOfExperience / 12 >= $this->minYearsOfExperience;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Behavioral/Specification/demo.php:
--------------------------------------------------------------------------------
1 | isSatisfiedBy($candidate)) {
66 | $candidatesToContact[] = $candidate;
67 | }
68 | }
69 |
70 | print_r($candidatesToContact);
71 |
--------------------------------------------------------------------------------
/src/Behavioral/State/Angry.php:
--------------------------------------------------------------------------------
1 | say("You too...");
10 | }
11 |
12 | public function hug(Person $context): void
13 | {
14 | $context->say("Hm...");
15 | $context->setState(new Neutral());
16 | }
17 |
18 | public function getName(Person $context, string $name): void
19 | {
20 | $context->say("{$name}. What's your problem?");
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/Behavioral/State/Happy.php:
--------------------------------------------------------------------------------
1 | say("Oh! That wasn't nice");
10 | $context->setState(new Neutral());
11 | }
12 |
13 | public function hug(Person $context): void
14 | {
15 | $context->say("Oh! That was nice, thanks");
16 | }
17 |
18 | public function getName(Person $context, string $name): void
19 | {
20 | $context->say("Oh! Hello dear friend. My name is {$name}");
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Behavioral/State/Mood.php:
--------------------------------------------------------------------------------
1 | say("What the heck do you want?");
10 | $context->setState(new Angry());
11 | }
12 |
13 | public function hug(Person $context): void
14 | {
15 | $context->say("Thanks");
16 | $context->setState(new Happy());
17 | }
18 |
19 | public function getName(Person $context, string $name): void
20 | {
21 | $context->say("My name is {$name}");
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/Behavioral/State/Person.php:
--------------------------------------------------------------------------------
1 | setState($mood);
13 | $this->name = $name;
14 | }
15 |
16 | public function setState(Mood $mood): void
17 | {
18 | $this->currentMood = $mood;
19 | }
20 |
21 | public function insult(): void
22 | {
23 | $this->currentMood->insult($this);
24 | }
25 |
26 | public function getName(): void
27 | {
28 | $this->currentMood->getName($this, $this->name);
29 | }
30 |
31 | public function hug(): void
32 | {
33 | $this->currentMood->hug($this);
34 | }
35 |
36 | public function say(string $msg): void
37 | {
38 | echo($msg . PHP_EOL);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Behavioral/State/demo.php:
--------------------------------------------------------------------------------
1 | getName();
9 | $jan->insult();
10 | $jan->getName();
11 | $jan->hug();
12 | $jan->getName();
13 | $jan->hug();
14 | $jan->getName();
15 |
--------------------------------------------------------------------------------
/src/Behavioral/Strategy/Context.php:
--------------------------------------------------------------------------------
1 | formatter = match ($outputType) {
12 | "json" => new JSONFormatter(),
13 | "xml" => new XMLFormatter(),
14 | "string" => new StringFormatter(),
15 | default => throw new \InvalidArgumentException("{$outputType} is not supported"),
16 | };
17 | }
18 |
19 | public function formatData(array $data): string
20 | {
21 | return $this->formatter->format($data);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Behavioral/Strategy/JSONFormatter.php:
--------------------------------------------------------------------------------
1 | addData($data, new SimpleXMLElement('