mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-09-26 06:19:20 +02:00
update deps & install rector
This commit is contained in:
@@ -3,9 +3,7 @@ language: php
|
|||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 7.2
|
- 7.4
|
||||||
- 7.3
|
|
||||||
- 7.4snapshot
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
@@ -3,14 +3,10 @@
|
|||||||
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
namespace DesignPatterns\Behavioral\ChainOfResponsibilities;
|
||||||
|
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
|
|
||||||
abstract class Handler
|
abstract class Handler
|
||||||
{
|
{
|
||||||
/**
|
private ?Handler $successor = null;
|
||||||
* @var Handler|null
|
|
||||||
*/
|
|
||||||
private $successor = null;
|
|
||||||
|
|
||||||
public function __construct(Handler $handler = null)
|
public function __construct(Handler $handler = null)
|
||||||
{
|
{
|
||||||
@@ -20,12 +16,8 @@ abstract class Handler
|
|||||||
/**
|
/**
|
||||||
* This approach by using a template method pattern ensures you that
|
* This approach by using a template method pattern ensures you that
|
||||||
* each subclass will not forget to call the successor
|
* each subclass will not forget to call the successor
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
*/
|
||||||
final public function handle(RequestInterface $request)
|
final public function handle(RequestInterface $request): ?string
|
||||||
{
|
{
|
||||||
$processed = $this->processing($request);
|
$processed = $this->processing($request);
|
||||||
|
|
||||||
@@ -37,5 +29,5 @@ abstract class Handler
|
|||||||
return $processed;
|
return $processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected function processing(RequestInterface $request);
|
abstract protected function processing(RequestInterface $request): ?string;
|
||||||
}
|
}
|
||||||
|
@@ -7,28 +7,16 @@ use Psr\Http\Message\RequestInterface;
|
|||||||
|
|
||||||
class HttpInMemoryCacheHandler extends Handler
|
class HttpInMemoryCacheHandler extends Handler
|
||||||
{
|
{
|
||||||
/**
|
private array $data;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $data;
|
|
||||||
|
|
||||||
/**
|
public function __construct(array $data, ?Handler $successor = null)
|
||||||
* @param array $data
|
|
||||||
* @param Handler|null $successor
|
|
||||||
*/
|
|
||||||
public function __construct(array $data, Handler $successor = null)
|
|
||||||
{
|
{
|
||||||
parent::__construct($successor);
|
parent::__construct($successor);
|
||||||
|
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function processing(RequestInterface $request): ?string
|
||||||
* @param RequestInterface $request
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
protected function processing(RequestInterface $request)
|
|
||||||
{
|
{
|
||||||
$key = sprintf(
|
$key = sprintf(
|
||||||
'%s?%s',
|
'%s?%s',
|
||||||
|
@@ -7,12 +7,7 @@ use Psr\Http\Message\RequestInterface;
|
|||||||
|
|
||||||
class SlowDatabaseHandler extends Handler
|
class SlowDatabaseHandler extends Handler
|
||||||
{
|
{
|
||||||
/**
|
protected function processing(RequestInterface $request): ?string
|
||||||
* @param RequestInterface $request
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
protected function processing(RequestInterface $request)
|
|
||||||
{
|
{
|
||||||
// this is a mockup, in production code you would ask a slow (compared to in-memory) DB for the results
|
// this is a mockup, in production code you would ask a slow (compared to in-memory) DB for the results
|
||||||
|
|
||||||
|
@@ -5,17 +5,13 @@ namespace DesignPatterns\Behavioral\ChainOfResponsibilities\Tests;
|
|||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Handler;
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\HttpInMemoryCacheHandler;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\HttpInMemoryCacheHandler;
|
||||||
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowDatabaseHandler;
|
use DesignPatterns\Behavioral\ChainOfResponsibilities\Responsible\SlowDatabaseHandler;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Psr\Http\Message\UriInterface;
|
use Psr\Http\Message\UriInterface;
|
||||||
|
|
||||||
class ChainTest extends TestCase
|
class ChainTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
private Handler $chain;
|
||||||
* @var Handler
|
|
||||||
*/
|
|
||||||
private $chain;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
|
|||||||
*/
|
*/
|
||||||
class AddMessageDateCommand implements UndoableCommand
|
class AddMessageDateCommand implements UndoableCommand
|
||||||
{
|
{
|
||||||
/**
|
private Receiver $output;
|
||||||
* @var Receiver
|
|
||||||
*/
|
|
||||||
private $output;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete command is built with different receivers.
|
* Each concrete command is built with different receivers.
|
||||||
* There can be one, many or completely no receivers, but there can be other commands in the parameters.
|
* There can be one, many or completely no receivers, but there can be other commands in the parameters.
|
||||||
*
|
|
||||||
* @param Receiver $console
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Receiver $console)
|
public function __construct(Receiver $console)
|
||||||
{
|
{
|
||||||
|
@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
|
|||||||
*/
|
*/
|
||||||
class HelloCommand implements Command
|
class HelloCommand implements Command
|
||||||
{
|
{
|
||||||
/**
|
private Receiver $output;
|
||||||
* @var Receiver
|
|
||||||
*/
|
|
||||||
private $output;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each concrete command is built with different receivers.
|
* Each concrete command is built with different receivers.
|
||||||
* There can be one, many or completely no receivers, but there can be other commands in the parameters
|
* There can be one, many or completely no receivers, but there can be other commands in the parameters
|
||||||
*
|
|
||||||
* @param Receiver $console
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Receiver $console)
|
public function __construct(Receiver $console)
|
||||||
{
|
{
|
||||||
|
@@ -8,16 +8,11 @@ namespace DesignPatterns\Behavioral\Command;
|
|||||||
*/
|
*/
|
||||||
class Invoker
|
class Invoker
|
||||||
{
|
{
|
||||||
/**
|
private Command $command;
|
||||||
* @var Command
|
|
||||||
*/
|
|
||||||
private $command;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* in the invoker we find this kind of method for subscribing the command
|
* in the invoker we find this kind of method for subscribing the command
|
||||||
* There can be also a stack, a list, a fixed set ...
|
* There can be also a stack, a list, a fixed set ...
|
||||||
*
|
|
||||||
* @param Command $cmd
|
|
||||||
*/
|
*/
|
||||||
public function setCommand(Command $cmd)
|
public function setCommand(Command $cmd)
|
||||||
{
|
{
|
||||||
|
@@ -3,23 +3,17 @@
|
|||||||
namespace DesignPatterns\Behavioral\Command;
|
namespace DesignPatterns\Behavioral\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receiver is specific service with its own contract and can be only concrete.
|
* Receiver is a specific service with its own contract and can be only concrete.
|
||||||
*/
|
*/
|
||||||
class Receiver
|
class Receiver
|
||||||
{
|
{
|
||||||
/**
|
private bool $enableDate = false;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $enableDate = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
private $output = [];
|
private array $output = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $str
|
|
||||||
*/
|
|
||||||
public function write(string $str)
|
public function write(string $str)
|
||||||
{
|
{
|
||||||
if ($this->enableDate) {
|
if ($this->enableDate) {
|
||||||
|
@@ -4,15 +4,8 @@ namespace DesignPatterns\Behavioral\Iterator;
|
|||||||
|
|
||||||
class Book
|
class Book
|
||||||
{
|
{
|
||||||
/**
|
private string $author;
|
||||||
* @var string
|
private string $title;
|
||||||
*/
|
|
||||||
private $author;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $title;
|
|
||||||
|
|
||||||
public function __construct(string $title, string $author)
|
public function __construct(string $title, string $author)
|
||||||
{
|
{
|
||||||
|
@@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Iterator;
|
namespace DesignPatterns\Behavioral\Iterator;
|
||||||
|
|
||||||
class BookList implements \Countable, \Iterator
|
use Countable;
|
||||||
|
use Iterator;
|
||||||
|
|
||||||
|
class BookList implements Countable, Iterator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Book[]
|
* @var Book[]
|
||||||
*/
|
*/
|
||||||
private $books = [];
|
private array $books = [];
|
||||||
|
private int $currentIndex = 0;
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $currentIndex = 0;
|
|
||||||
|
|
||||||
public function addBook(Book $book)
|
public function addBook(Book $book)
|
||||||
{
|
{
|
||||||
|
@@ -4,14 +4,8 @@ namespace DesignPatterns\Behavioral\Mediator;
|
|||||||
|
|
||||||
abstract class Colleague
|
abstract class Colleague
|
||||||
{
|
{
|
||||||
/**
|
protected Mediator $mediator;
|
||||||
* @var Mediator
|
|
||||||
*/
|
|
||||||
protected $mediator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Mediator $mediator
|
|
||||||
*/
|
|
||||||
public function setMediator(Mediator $mediator)
|
public function setMediator(Mediator $mediator)
|
||||||
{
|
{
|
||||||
$this->mediator = $mediator;
|
$this->mediator = $mediator;
|
||||||
|
@@ -11,7 +11,7 @@ class MediatorTest extends TestCase
|
|||||||
{
|
{
|
||||||
public function testOutputHelloWorld()
|
public function testOutputHelloWorld()
|
||||||
{
|
{
|
||||||
$mediator = new UserRepositoryUiMediator(new UserRepository(), new UI());
|
$mediator = new UserRepositoryUiMediator(new UserRepository(), new Ui());
|
||||||
|
|
||||||
$this->expectOutputString('User: Dominik');
|
$this->expectOutputString('User: Dominik');
|
||||||
$mediator->printInfoAbout('Dominik');
|
$mediator->printInfoAbout('Dominik');
|
||||||
|
@@ -4,15 +4,8 @@ namespace DesignPatterns\Behavioral\Mediator;
|
|||||||
|
|
||||||
class UserRepositoryUiMediator implements Mediator
|
class UserRepositoryUiMediator implements Mediator
|
||||||
{
|
{
|
||||||
/**
|
private UserRepository $userRepository;
|
||||||
* @var UserRepository
|
private Ui $ui;
|
||||||
*/
|
|
||||||
private $userRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Ui
|
|
||||||
*/
|
|
||||||
private $ui;
|
|
||||||
|
|
||||||
public function __construct(UserRepository $userRepository, Ui $ui)
|
public function __construct(UserRepository $userRepository, Ui $ui)
|
||||||
{
|
{
|
||||||
|
@@ -4,23 +4,14 @@ namespace DesignPatterns\Behavioral\Memento;
|
|||||||
|
|
||||||
class Memento
|
class Memento
|
||||||
{
|
{
|
||||||
/**
|
private State $state;
|
||||||
* @var State
|
|
||||||
*/
|
|
||||||
private $state;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param State $stateToSave
|
|
||||||
*/
|
|
||||||
public function __construct(State $stateToSave)
|
public function __construct(State $stateToSave)
|
||||||
{
|
{
|
||||||
$this->state = $stateToSave;
|
$this->state = $stateToSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getState(): State
|
||||||
* @return State
|
|
||||||
*/
|
|
||||||
public function getState()
|
|
||||||
{
|
{
|
||||||
return $this->state;
|
return $this->state;
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Memento;
|
namespace DesignPatterns\Behavioral\Memento;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class State
|
class State
|
||||||
{
|
{
|
||||||
const STATE_CREATED = 'created';
|
const STATE_CREATED = 'created';
|
||||||
@@ -9,24 +11,18 @@ class State
|
|||||||
const STATE_ASSIGNED = 'assigned';
|
const STATE_ASSIGNED = 'assigned';
|
||||||
const STATE_CLOSED = 'closed';
|
const STATE_CLOSED = 'closed';
|
||||||
|
|
||||||
/**
|
private string $state;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $state;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
private static $validStates = [
|
private static array $validStates = [
|
||||||
self::STATE_CREATED,
|
self::STATE_CREATED,
|
||||||
self::STATE_OPENED,
|
self::STATE_OPENED,
|
||||||
self::STATE_ASSIGNED,
|
self::STATE_ASSIGNED,
|
||||||
self::STATE_CLOSED,
|
self::STATE_CLOSED,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $state
|
|
||||||
*/
|
|
||||||
public function __construct(string $state)
|
public function __construct(string $state)
|
||||||
{
|
{
|
||||||
self::ensureIsValidState($state);
|
self::ensureIsValidState($state);
|
||||||
@@ -37,7 +33,7 @@ class State
|
|||||||
private static function ensureIsValidState(string $state)
|
private static function ensureIsValidState(string $state)
|
||||||
{
|
{
|
||||||
if (!in_array($state, self::$validStates)) {
|
if (!in_array($state, self::$validStates)) {
|
||||||
throw new \InvalidArgumentException('Invalid state given');
|
throw new InvalidArgumentException('Invalid state given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,10 +7,7 @@ namespace DesignPatterns\Behavioral\Memento;
|
|||||||
*/
|
*/
|
||||||
class Ticket
|
class Ticket
|
||||||
{
|
{
|
||||||
/**
|
private State $currentState;
|
||||||
* @var State
|
|
||||||
*/
|
|
||||||
private $currentState;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@@ -4,14 +4,8 @@ namespace DesignPatterns\Behavioral\NullObject;
|
|||||||
|
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
/**
|
private Logger $logger;
|
||||||
* @var Logger
|
|
||||||
*/
|
|
||||||
private $logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Logger $logger
|
|
||||||
*/
|
|
||||||
public function __construct(Logger $logger)
|
public function __construct(Logger $logger)
|
||||||
{
|
{
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
|
@@ -2,33 +2,30 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
|
use SplSubject;
|
||||||
|
use SplObjectStorage;
|
||||||
|
use SplObserver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User implements the observed object (called Subject), it maintains a list of observers and sends notifications to
|
* User implements the observed object (called Subject), it maintains a list of observers and sends notifications to
|
||||||
* them in case changes are made on the User object
|
* them in case changes are made on the User object
|
||||||
*/
|
*/
|
||||||
class User implements \SplSubject
|
class User implements SplSubject
|
||||||
{
|
{
|
||||||
/**
|
private string $email;
|
||||||
* @var string
|
private SplObjectStorage $observers;
|
||||||
*/
|
|
||||||
private $email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \SplObjectStorage
|
|
||||||
*/
|
|
||||||
private $observers;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->observers = new \SplObjectStorage();
|
$this->observers = new SplObjectStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attach(\SplObserver $observer)
|
public function attach(SplObserver $observer)
|
||||||
{
|
{
|
||||||
$this->observers->attach($observer);
|
$this->observers->attach($observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function detach(\SplObserver $observer)
|
public function detach(SplObserver $observer)
|
||||||
{
|
{
|
||||||
$this->observers->detach($observer);
|
$this->observers->detach($observer);
|
||||||
}
|
}
|
||||||
@@ -41,7 +38,7 @@ class User implements \SplSubject
|
|||||||
|
|
||||||
public function notify()
|
public function notify()
|
||||||
{
|
{
|
||||||
/** @var \SplObserver $observer */
|
/** @var SplObserver $observer */
|
||||||
foreach ($this->observers as $observer) {
|
foreach ($this->observers as $observer) {
|
||||||
$observer->update($this);
|
$observer->update($this);
|
||||||
}
|
}
|
||||||
|
@@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Observer;
|
namespace DesignPatterns\Behavioral\Observer;
|
||||||
|
|
||||||
|
use SplObserver;
|
||||||
use SplSubject;
|
use SplSubject;
|
||||||
|
|
||||||
class UserObserver implements \SplObserver
|
class UserObserver implements SplObserver
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var SplSubject[]
|
* @var SplSubject[]
|
||||||
*/
|
*/
|
||||||
private $changedUsers = [];
|
private array $changedUsers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It is called by the Subject, usually by SplSubject::notify()
|
* It is called by the Subject, usually by SplSubject::notify()
|
||||||
*
|
|
||||||
* @param SplSubject $subject
|
|
||||||
*/
|
*/
|
||||||
public function update(SplSubject $subject)
|
public function update(SplSubject $subject)
|
||||||
{
|
{
|
||||||
|
@@ -7,7 +7,7 @@ class AndSpecification implements Specification
|
|||||||
/**
|
/**
|
||||||
* @var Specification[]
|
* @var Specification[]
|
||||||
*/
|
*/
|
||||||
private $specifications;
|
private array $specifications;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Specification[] $specifications
|
* @param Specification[] $specifications
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Specification;
|
|||||||
|
|
||||||
class Item
|
class Item
|
||||||
{
|
{
|
||||||
/**
|
private float $price;
|
||||||
* @var float
|
|
||||||
*/
|
|
||||||
private $price;
|
|
||||||
|
|
||||||
public function __construct(float $price)
|
public function __construct(float $price)
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Specification;
|
|||||||
|
|
||||||
class NotSpecification implements Specification
|
class NotSpecification implements Specification
|
||||||
{
|
{
|
||||||
/**
|
private Specification $specification;
|
||||||
* @var Specification
|
|
||||||
*/
|
|
||||||
private $specification;
|
|
||||||
|
|
||||||
public function __construct(Specification $specification)
|
public function __construct(Specification $specification)
|
||||||
{
|
{
|
||||||
|
@@ -7,7 +7,7 @@ class OrSpecification implements Specification
|
|||||||
/**
|
/**
|
||||||
* @var Specification[]
|
* @var Specification[]
|
||||||
*/
|
*/
|
||||||
private $specifications;
|
private array $specifications;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Specification[] $specifications
|
* @param Specification[] $specifications
|
||||||
@@ -27,6 +27,7 @@ class OrSpecification implements Specification
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,21 +4,10 @@ namespace DesignPatterns\Behavioral\Specification;
|
|||||||
|
|
||||||
class PriceSpecification implements Specification
|
class PriceSpecification implements Specification
|
||||||
{
|
{
|
||||||
/**
|
private ?float $maxPrice;
|
||||||
* @var float|null
|
private ?float $minPrice;
|
||||||
*/
|
|
||||||
private $maxPrice;
|
|
||||||
|
|
||||||
/**
|
public function __construct(?float $minPrice, ?float $maxPrice)
|
||||||
* @var float|null
|
|
||||||
*/
|
|
||||||
private $minPrice;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param float $minPrice
|
|
||||||
* @param float $maxPrice
|
|
||||||
*/
|
|
||||||
public function __construct($minPrice, $maxPrice)
|
|
||||||
{
|
{
|
||||||
$this->minPrice = $minPrice;
|
$this->minPrice = $minPrice;
|
||||||
$this->maxPrice = $maxPrice;
|
$this->maxPrice = $maxPrice;
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\State;
|
|||||||
|
|
||||||
class OrderContext
|
class OrderContext
|
||||||
{
|
{
|
||||||
/**
|
private State $state;
|
||||||
* @var State
|
|
||||||
*/
|
|
||||||
private $state;
|
|
||||||
|
|
||||||
public static function create(): OrderContext
|
public static function create(): OrderContext
|
||||||
{
|
{
|
||||||
|
@@ -4,17 +4,14 @@ namespace DesignPatterns\Behavioral\Strategy;
|
|||||||
|
|
||||||
class Context
|
class Context
|
||||||
{
|
{
|
||||||
/**
|
private Comparator $comparator;
|
||||||
* @var Comparator
|
|
||||||
*/
|
|
||||||
private $comparator;
|
|
||||||
|
|
||||||
public function __construct(Comparator $comparator)
|
public function __construct(Comparator $comparator)
|
||||||
{
|
{
|
||||||
$this->comparator = $comparator;
|
$this->comparator = $comparator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function executeStrategy(array $elements) : array
|
public function executeStrategy(array $elements): array
|
||||||
{
|
{
|
||||||
uasort($elements, [$this->comparator, 'compare']);
|
uasort($elements, [$this->comparator, 'compare']);
|
||||||
|
|
||||||
|
@@ -2,18 +2,14 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\Strategy;
|
namespace DesignPatterns\Behavioral\Strategy;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
class DateComparator implements Comparator
|
class DateComparator implements Comparator
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @param mixed $a
|
|
||||||
* @param mixed $b
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function compare($a, $b): int
|
public function compare($a, $b): int
|
||||||
{
|
{
|
||||||
$aDate = new \DateTime($a['date']);
|
$aDate = new DateTime($a['date']);
|
||||||
$bDate = new \DateTime($b['date']);
|
$bDate = new DateTime($b['date']);
|
||||||
|
|
||||||
return $aDate <=> $bDate;
|
return $aDate <=> $bDate;
|
||||||
}
|
}
|
||||||
|
@@ -4,12 +4,6 @@ namespace DesignPatterns\Behavioral\Strategy;
|
|||||||
|
|
||||||
class IdComparator implements Comparator
|
class IdComparator implements Comparator
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @param mixed $a
|
|
||||||
* @param mixed $b
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function compare($a, $b): int
|
public function compare($a, $b): int
|
||||||
{
|
{
|
||||||
return $a['id'] <=> $b['id'];
|
return $a['id'] <=> $b['id'];
|
||||||
|
@@ -9,7 +9,7 @@ class CityJourney extends Journey
|
|||||||
return "Eat, drink, take photos and sleep";
|
return "Eat, drink, take photos and sleep";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buyGift(): string
|
protected function buyGift(): ?string
|
||||||
{
|
{
|
||||||
return "Buy a gift";
|
return "Buy a gift";
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ abstract class Journey
|
|||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
private $thingsToDo = [];
|
private array $thingsToDo = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the public service provided by this class and its subclasses.
|
* This is the public service provided by this class and its subclasses.
|
||||||
@@ -37,10 +37,8 @@ abstract class Journey
|
|||||||
/**
|
/**
|
||||||
* This method is also part of the algorithm but it is optional.
|
* This method is also part of the algorithm but it is optional.
|
||||||
* You can override it only if you need to
|
* You can override it only if you need to
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
*/
|
||||||
protected function buyGift()
|
protected function buyGift(): ?string
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
|
namespace DesignPatterns\Behavioral\TemplateMethod\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Behavioral\TemplateMethod;
|
use DesignPatterns\Behavioral\TemplateMethod\BeachJourney;
|
||||||
|
use DesignPatterns\Behavioral\TemplateMethod\CityJourney;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class JourneyTest extends TestCase
|
class JourneyTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testCanGetOnVacationOnTheBeach()
|
public function testCanGetOnVacationOnTheBeach()
|
||||||
{
|
{
|
||||||
$beachJourney = new TemplateMethod\BeachJourney();
|
$beachJourney = new BeachJourney();
|
||||||
$beachJourney->takeATrip();
|
$beachJourney->takeATrip();
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
@@ -20,7 +21,7 @@ class JourneyTest extends TestCase
|
|||||||
|
|
||||||
public function testCanGetOnAJourneyToACity()
|
public function testCanGetOnAJourneyToACity()
|
||||||
{
|
{
|
||||||
$cityJourney = new TemplateMethod\CityJourney();
|
$cityJourney = new CityJourney();
|
||||||
$cityJourney->takeATrip();
|
$cityJourney->takeATrip();
|
||||||
|
|
||||||
$this->assertSame(
|
$this->assertSame(
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Visitor;
|
|||||||
|
|
||||||
class Group implements Role
|
class Group implements Role
|
||||||
{
|
{
|
||||||
/**
|
private string $name;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function __construct(string $name)
|
public function __construct(string $name)
|
||||||
{
|
{
|
||||||
|
@@ -7,7 +7,7 @@ class RecordingVisitor implements RoleVisitor
|
|||||||
/**
|
/**
|
||||||
* @var Role[]
|
* @var Role[]
|
||||||
*/
|
*/
|
||||||
private $visited = [];
|
private array $visited = [];
|
||||||
|
|
||||||
public function visitGroup(Group $role)
|
public function visitGroup(Group $role)
|
||||||
{
|
{
|
||||||
|
@@ -2,35 +2,34 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Tests\Visitor\Tests;
|
namespace DesignPatterns\Tests\Visitor\Tests;
|
||||||
|
|
||||||
|
use DesignPatterns\Behavioral\Visitor\RecordingVisitor;
|
||||||
|
use DesignPatterns\Behavioral\Visitor\User;
|
||||||
|
use DesignPatterns\Behavioral\Visitor\Group;
|
||||||
|
use DesignPatterns\Behavioral\Visitor\Role;
|
||||||
use DesignPatterns\Behavioral\Visitor;
|
use DesignPatterns\Behavioral\Visitor;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class VisitorTest extends TestCase
|
class VisitorTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
private RecordingVisitor $visitor;
|
||||||
* @var Visitor\RecordingVisitor
|
|
||||||
*/
|
|
||||||
private $visitor;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->visitor = new Visitor\RecordingVisitor();
|
$this->visitor = new RecordingVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideRoles()
|
public function provideRoles()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
[new Visitor\User('Dominik')],
|
[new User('Dominik')],
|
||||||
[new Visitor\Group('Administrators')],
|
[new Group('Administrators')],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider provideRoles
|
* @dataProvider provideRoles
|
||||||
*
|
|
||||||
* @param Visitor\Role $role
|
|
||||||
*/
|
*/
|
||||||
public function testVisitSomeRole(Visitor\Role $role)
|
public function testVisitSomeRole(Role $role)
|
||||||
{
|
{
|
||||||
$role->accept($this->visitor);
|
$role->accept($this->visitor);
|
||||||
$this->assertSame($role, $this->visitor->getVisited()[0]);
|
$this->assertSame($role, $this->visitor->getVisited()[0]);
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Behavioral\Visitor;
|
|||||||
|
|
||||||
class User implements Role
|
class User implements Role
|
||||||
{
|
{
|
||||||
/**
|
private string $name;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function __construct(string $name)
|
public function __construct(string $name)
|
||||||
{
|
{
|
||||||
|
@@ -2,38 +2,39 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Door;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Engine;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Wheel;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Car;
|
||||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||||
|
|
||||||
class CarBuilder implements Builder
|
class CarBuilder implements Builder
|
||||||
{
|
{
|
||||||
/**
|
private Car $car;
|
||||||
* @var Parts\Car
|
|
||||||
*/
|
|
||||||
private $car;
|
|
||||||
|
|
||||||
public function addDoors()
|
public function addDoors()
|
||||||
{
|
{
|
||||||
$this->car->setPart('rightDoor', new Parts\Door());
|
$this->car->setPart('rightDoor', new Door());
|
||||||
$this->car->setPart('leftDoor', new Parts\Door());
|
$this->car->setPart('leftDoor', new Door());
|
||||||
$this->car->setPart('trunkLid', new Parts\Door());
|
$this->car->setPart('trunkLid', new Door());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addEngine()
|
public function addEngine()
|
||||||
{
|
{
|
||||||
$this->car->setPart('engine', new Parts\Engine());
|
$this->car->setPart('engine', new Engine());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWheel()
|
public function addWheel()
|
||||||
{
|
{
|
||||||
$this->car->setPart('wheelLF', new Parts\Wheel());
|
$this->car->setPart('wheelLF', new Wheel());
|
||||||
$this->car->setPart('wheelRF', new Parts\Wheel());
|
$this->car->setPart('wheelRF', new Wheel());
|
||||||
$this->car->setPart('wheelLR', new Parts\Wheel());
|
$this->car->setPart('wheelLR', new Wheel());
|
||||||
$this->car->setPart('wheelRR', new Parts\Wheel());
|
$this->car->setPart('wheelRR', new Wheel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createVehicle()
|
public function createVehicle()
|
||||||
{
|
{
|
||||||
$this->car = new Parts\Car();
|
$this->car = new Car();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVehicle(): Vehicle
|
public function getVehicle(): Vehicle
|
||||||
|
@@ -7,13 +7,9 @@ abstract class Vehicle
|
|||||||
/**
|
/**
|
||||||
* @var object[]
|
* @var object[]
|
||||||
*/
|
*/
|
||||||
private $data = [];
|
private array $data = [];
|
||||||
|
|
||||||
/**
|
public function setPart(string $key, object $value)
|
||||||
* @param string $key
|
|
||||||
* @param object $value
|
|
||||||
*/
|
|
||||||
public function setPart($key, $value)
|
|
||||||
{
|
{
|
||||||
$this->data[$key] = $value;
|
$this->data[$key] = $value;
|
||||||
}
|
}
|
||||||
|
@@ -2,39 +2,40 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\Builder;
|
namespace DesignPatterns\Creational\Builder;
|
||||||
|
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Door;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Engine;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Wheel;
|
||||||
|
use DesignPatterns\Creational\Builder\Parts\Truck;
|
||||||
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
use DesignPatterns\Creational\Builder\Parts\Vehicle;
|
||||||
|
|
||||||
class TruckBuilder implements Builder
|
class TruckBuilder implements Builder
|
||||||
{
|
{
|
||||||
/**
|
private Truck $truck;
|
||||||
* @var Parts\Truck
|
|
||||||
*/
|
|
||||||
private $truck;
|
|
||||||
|
|
||||||
public function addDoors()
|
public function addDoors()
|
||||||
{
|
{
|
||||||
$this->truck->setPart('rightDoor', new Parts\Door());
|
$this->truck->setPart('rightDoor', new Door());
|
||||||
$this->truck->setPart('leftDoor', new Parts\Door());
|
$this->truck->setPart('leftDoor', new Door());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addEngine()
|
public function addEngine()
|
||||||
{
|
{
|
||||||
$this->truck->setPart('truckEngine', new Parts\Engine());
|
$this->truck->setPart('truckEngine', new Engine());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addWheel()
|
public function addWheel()
|
||||||
{
|
{
|
||||||
$this->truck->setPart('wheel1', new Parts\Wheel());
|
$this->truck->setPart('wheel1', new Wheel());
|
||||||
$this->truck->setPart('wheel2', new Parts\Wheel());
|
$this->truck->setPart('wheel2', new Wheel());
|
||||||
$this->truck->setPart('wheel3', new Parts\Wheel());
|
$this->truck->setPart('wheel3', new Wheel());
|
||||||
$this->truck->setPart('wheel4', new Parts\Wheel());
|
$this->truck->setPart('wheel4', new Wheel());
|
||||||
$this->truck->setPart('wheel5', new Parts\Wheel());
|
$this->truck->setPart('wheel5', new Wheel());
|
||||||
$this->truck->setPart('wheel6', new Parts\Wheel());
|
$this->truck->setPart('wheel6', new Wheel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createVehicle()
|
public function createVehicle()
|
||||||
{
|
{
|
||||||
$this->truck = new Parts\Truck();
|
$this->truck = new Truck();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVehicle(): Vehicle
|
public function getVehicle(): Vehicle
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\FactoryMethod;
|
|||||||
|
|
||||||
class FileLogger implements Logger
|
class FileLogger implements Logger
|
||||||
{
|
{
|
||||||
/**
|
private string $filePath;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $filePath;
|
|
||||||
|
|
||||||
public function __construct(string $filePath)
|
public function __construct(string $filePath)
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\FactoryMethod;
|
|||||||
|
|
||||||
class FileLoggerFactory implements LoggerFactory
|
class FileLoggerFactory implements LoggerFactory
|
||||||
{
|
{
|
||||||
/**
|
private string $filePath;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $filePath;
|
|
||||||
|
|
||||||
public function __construct(string $filePath)
|
public function __construct(string $filePath)
|
||||||
{
|
{
|
||||||
|
@@ -10,7 +10,7 @@ final class Multiton
|
|||||||
/**
|
/**
|
||||||
* @var Multiton[]
|
* @var Multiton[]
|
||||||
*/
|
*/
|
||||||
private static $instances = [];
|
private static array $instances = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this is private to prevent from creating arbitrary instances
|
* this is private to prevent from creating arbitrary instances
|
||||||
|
@@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\Pool;
|
namespace DesignPatterns\Creational\Pool;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
class StringReverseWorker
|
class StringReverseWorker
|
||||||
{
|
{
|
||||||
/**
|
private DateTime $createdAt;
|
||||||
* @var \DateTime
|
|
||||||
*/
|
|
||||||
private $createdAt;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->createdAt = new \DateTime();
|
$this->createdAt = new DateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(string $text)
|
public function run(string $text)
|
||||||
|
@@ -2,17 +2,19 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\Pool;
|
namespace DesignPatterns\Creational\Pool;
|
||||||
|
|
||||||
class WorkerPool implements \Countable
|
use Countable;
|
||||||
|
|
||||||
|
class WorkerPool implements Countable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var StringReverseWorker[]
|
* @var StringReverseWorker[]
|
||||||
*/
|
*/
|
||||||
private $occupiedWorkers = [];
|
private array $occupiedWorkers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var StringReverseWorker[]
|
* @var StringReverseWorker[]
|
||||||
*/
|
*/
|
||||||
private $freeWorkers = [];
|
private array $freeWorkers = [];
|
||||||
|
|
||||||
public function get(): StringReverseWorker
|
public function get(): StringReverseWorker
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Prototype;
|
|||||||
|
|
||||||
class BarBookPrototype extends BookPrototype
|
class BarBookPrototype extends BookPrototype
|
||||||
{
|
{
|
||||||
/**
|
protected string $category = 'Bar';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $category = 'Bar';
|
|
||||||
|
|
||||||
public function __clone()
|
public function __clone()
|
||||||
{
|
{
|
||||||
|
@@ -4,15 +4,8 @@ namespace DesignPatterns\Creational\Prototype;
|
|||||||
|
|
||||||
abstract class BookPrototype
|
abstract class BookPrototype
|
||||||
{
|
{
|
||||||
/**
|
protected string $title;
|
||||||
* @var string
|
protected string $category;
|
||||||
*/
|
|
||||||
protected $title;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $category;
|
|
||||||
|
|
||||||
abstract public function __clone();
|
abstract public function __clone();
|
||||||
|
|
||||||
@@ -21,7 +14,7 @@ abstract class BookPrototype
|
|||||||
return $this->title;
|
return $this->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTitle($title)
|
public function setTitle(string $title)
|
||||||
{
|
{
|
||||||
$this->title = $title;
|
$this->title = $title;
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Prototype;
|
|||||||
|
|
||||||
class FooBookPrototype extends BookPrototype
|
class FooBookPrototype extends BookPrototype
|
||||||
{
|
{
|
||||||
/**
|
protected string $category = 'Foo';
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $category = 'Foo';
|
|
||||||
|
|
||||||
public function __clone()
|
public function __clone()
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Creational\Singleton;
|
|||||||
|
|
||||||
final class Singleton
|
final class Singleton
|
||||||
{
|
{
|
||||||
/**
|
private static ?Singleton $instance = null;
|
||||||
* @var Singleton
|
|
||||||
*/
|
|
||||||
private static $instance;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the instance via lazy initialization (created on first usage)
|
* gets the instance via lazy initialization (created on first usage)
|
||||||
|
@@ -2,17 +2,14 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\StaticFactory;
|
namespace DesignPatterns\Creational\StaticFactory;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note1: Remember, static means global state which is evil because it can't be mocked for tests
|
* Note1: Remember, static means global state which is evil because it can't be mocked for tests
|
||||||
* Note2: Cannot be subclassed or mock-upped or have multiple different instances.
|
* Note2: Cannot be subclassed or mock-upped or have multiple different instances.
|
||||||
*/
|
*/
|
||||||
final class StaticFactory
|
final class StaticFactory
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @param string $type
|
|
||||||
*
|
|
||||||
* @return Formatter
|
|
||||||
*/
|
|
||||||
public static function factory(string $type): Formatter
|
public static function factory(string $type): Formatter
|
||||||
{
|
{
|
||||||
if ($type == 'number') {
|
if ($type == 'number') {
|
||||||
@@ -21,6 +18,6 @@ final class StaticFactory
|
|||||||
return new FormatString();
|
return new FormatString();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \InvalidArgumentException('Unknown format given');
|
throw new InvalidArgumentException('Unknown format given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Creational\StaticFactory\Tests;
|
namespace DesignPatterns\Creational\StaticFactory\Tests;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
use DesignPatterns\Creational\StaticFactory\FormatNumber;
|
use DesignPatterns\Creational\StaticFactory\FormatNumber;
|
||||||
use DesignPatterns\Creational\StaticFactory\FormatString;
|
use DesignPatterns\Creational\StaticFactory\FormatString;
|
||||||
use DesignPatterns\Creational\StaticFactory\StaticFactory;
|
use DesignPatterns\Creational\StaticFactory\StaticFactory;
|
||||||
@@ -21,7 +22,7 @@ class StaticFactoryTest extends TestCase
|
|||||||
|
|
||||||
public function testException()
|
public function testException()
|
||||||
{
|
{
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
StaticFactory::factory('object');
|
StaticFactory::factory('object');
|
||||||
}
|
}
|
||||||
|
@@ -2,21 +2,16 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\EAV;
|
namespace DesignPatterns\More\EAV;
|
||||||
|
|
||||||
|
use SplObjectStorage;
|
||||||
|
|
||||||
class Attribute
|
class Attribute
|
||||||
{
|
{
|
||||||
/**
|
private SplObjectStorage $values;
|
||||||
* @var \SplObjectStorage
|
private string $name;
|
||||||
*/
|
|
||||||
private $values;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function __construct(string $name)
|
public function __construct(string $name)
|
||||||
{
|
{
|
||||||
$this->values = new \SplObjectStorage();
|
$this->values = new SplObjectStorage();
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,10 +20,7 @@ class Attribute
|
|||||||
$this->values->attach($value);
|
$this->values->attach($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getValues(): SplObjectStorage
|
||||||
* @return \SplObjectStorage
|
|
||||||
*/
|
|
||||||
public function getValues(): \SplObjectStorage
|
|
||||||
{
|
{
|
||||||
return $this->values;
|
return $this->values;
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ class Entity
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $name;
|
private string $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
@@ -22,6 +22,7 @@ class Entity
|
|||||||
*/
|
*/
|
||||||
public function __construct(string $name, $values)
|
public function __construct(string $name, $values)
|
||||||
{
|
{
|
||||||
|
/** @var SplObjectStorage<Value,Value> values */
|
||||||
$this->values = new SplObjectStorage();
|
$this->values = new SplObjectStorage();
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
|
|
||||||
|
@@ -4,15 +4,8 @@ namespace DesignPatterns\More\EAV;
|
|||||||
|
|
||||||
class Value
|
class Value
|
||||||
{
|
{
|
||||||
/**
|
private Attribute $attribute;
|
||||||
* @var Attribute
|
private string $name;
|
||||||
*/
|
|
||||||
private $attribute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function __construct(Attribute $attribute, string $name)
|
public function __construct(Attribute $attribute, string $name)
|
||||||
{
|
{
|
||||||
|
@@ -4,25 +4,10 @@ namespace DesignPatterns\More\Repository\Domain;
|
|||||||
|
|
||||||
class Post
|
class Post
|
||||||
{
|
{
|
||||||
/**
|
private PostId $id;
|
||||||
* @var PostId
|
private PostStatus $status;
|
||||||
*/
|
private string $title;
|
||||||
private $id;
|
private string $text;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var PostStatus
|
|
||||||
*/
|
|
||||||
private $status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $title;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $text;
|
|
||||||
|
|
||||||
public static function draft(PostId $id, string $title, string $text): Post
|
public static function draft(PostId $id, string $title, string $text): Post
|
||||||
{
|
{
|
||||||
@@ -44,12 +29,6 @@ class Post
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param PostId $id
|
|
||||||
* @param PostStatus $status
|
|
||||||
* @param string $title
|
|
||||||
* @param string $text
|
|
||||||
*/
|
|
||||||
private function __construct(PostId $id, PostStatus $status, string $title, string $text)
|
private function __construct(PostId $id, PostStatus $status, string $title, string $text)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\Repository\Domain;
|
namespace DesignPatterns\More\Repository\Domain;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a perfect example of a value object that is identifiable by it's value alone and
|
* This is a perfect example of a value object that is identifiable by it's value alone and
|
||||||
* is guaranteed to be valid each time an instance is created. Another important property of value objects
|
* is guaranteed to be valid each time an instance is created. Another important property of value objects
|
||||||
@@ -11,12 +13,9 @@ namespace DesignPatterns\More\Repository\Domain;
|
|||||||
*/
|
*/
|
||||||
class PostId
|
class PostId
|
||||||
{
|
{
|
||||||
/**
|
private int $id;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
public static function fromInt(int $id)
|
public static function fromInt(int $id): PostId
|
||||||
{
|
{
|
||||||
self::ensureIsValid($id);
|
self::ensureIsValid($id);
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ class PostId
|
|||||||
private static function ensureIsValid(int $id)
|
private static function ensureIsValid(int $id)
|
||||||
{
|
{
|
||||||
if ($id <= 0) {
|
if ($id <= 0) {
|
||||||
throw new \InvalidArgumentException('Invalid PostId given');
|
throw new InvalidArgumentException('Invalid PostId given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\Repository\Domain;
|
namespace DesignPatterns\More\Repository\Domain;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Like PostId, this is a value object which holds the value of the current status of a Post. It can be constructed
|
* Like PostId, this is a value object which holds the value of the current status of a Post. It can be constructed
|
||||||
* either from a string or int and is able to validate itself. An instance can then be converted back to int or string.
|
* either from a string or int and is able to validate itself. An instance can then be converted back to int or string.
|
||||||
@@ -14,20 +16,13 @@ class PostStatus
|
|||||||
const STATE_DRAFT = 'draft';
|
const STATE_DRAFT = 'draft';
|
||||||
const STATE_PUBLISHED = 'published';
|
const STATE_PUBLISHED = 'published';
|
||||||
|
|
||||||
private static $validStates = [
|
private static array $validStates = [
|
||||||
self::STATE_DRAFT_ID => self::STATE_DRAFT,
|
self::STATE_DRAFT_ID => self::STATE_DRAFT,
|
||||||
self::STATE_PUBLISHED_ID => self::STATE_PUBLISHED,
|
self::STATE_PUBLISHED_ID => self::STATE_PUBLISHED,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
private int $id;
|
||||||
* @var int
|
private string $name;
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public static function fromInt(int $statusId)
|
public static function fromInt(int $statusId)
|
||||||
{
|
{
|
||||||
@@ -39,8 +34,13 @@ class PostStatus
|
|||||||
public static function fromString(string $status)
|
public static function fromString(string $status)
|
||||||
{
|
{
|
||||||
self::ensureIsValidName($status);
|
self::ensureIsValidName($status);
|
||||||
|
$state = array_search($status, self::$validStates);
|
||||||
|
|
||||||
return new self(array_search($status, self::$validStates), $status);
|
if ($state === false) {
|
||||||
|
throw new InvalidArgumentException('Invalid state given!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self($state, $status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function __construct(int $id, string $name)
|
private function __construct(int $id, string $name)
|
||||||
@@ -66,7 +66,7 @@ class PostStatus
|
|||||||
private static function ensureIsValidId(int $status)
|
private static function ensureIsValidId(int $status)
|
||||||
{
|
{
|
||||||
if (!in_array($status, array_keys(self::$validStates), true)) {
|
if (!in_array($status, array_keys(self::$validStates), true)) {
|
||||||
throw new \InvalidArgumentException('Invalid status id given');
|
throw new InvalidArgumentException('Invalid status id given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class PostStatus
|
|||||||
private static function ensureIsValidName(string $status)
|
private static function ensureIsValidName(string $status)
|
||||||
{
|
{
|
||||||
if (!in_array($status, self::$validStates, true)) {
|
if (!in_array($status, self::$validStates, true)) {
|
||||||
throw new \InvalidArgumentException('Invalid status name given');
|
throw new InvalidArgumentException('Invalid status name given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,17 +2,12 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\Repository;
|
namespace DesignPatterns\More\Repository;
|
||||||
|
|
||||||
|
use OutOfBoundsException;
|
||||||
|
|
||||||
class InMemoryPersistence implements Persistence
|
class InMemoryPersistence implements Persistence
|
||||||
{
|
{
|
||||||
/**
|
private array $data = [];
|
||||||
* @var array
|
private int $lastId = 0;
|
||||||
*/
|
|
||||||
private $data = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $lastId = 0;
|
|
||||||
|
|
||||||
public function generateId(): int
|
public function generateId(): int
|
||||||
{
|
{
|
||||||
@@ -29,7 +24,7 @@ class InMemoryPersistence implements Persistence
|
|||||||
public function retrieve(int $id): array
|
public function retrieve(int $id): array
|
||||||
{
|
{
|
||||||
if (!isset($this->data[$id])) {
|
if (!isset($this->data[$id])) {
|
||||||
throw new \OutOfBoundsException(sprintf('No data found for ID %d', $id));
|
throw new OutOfBoundsException(sprintf('No data found for ID %d', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->data[$id];
|
return $this->data[$id];
|
||||||
@@ -38,7 +33,7 @@ class InMemoryPersistence implements Persistence
|
|||||||
public function delete(int $id)
|
public function delete(int $id)
|
||||||
{
|
{
|
||||||
if (!isset($this->data[$id])) {
|
if (!isset($this->data[$id])) {
|
||||||
throw new \OutOfBoundsException(sprintf('No data found for ID %d', $id));
|
throw new OutOfBoundsException(sprintf('No data found for ID %d', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($this->data[$id]);
|
unset($this->data[$id]);
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\Repository;
|
namespace DesignPatterns\More\Repository;
|
||||||
|
|
||||||
|
use OutOfBoundsException;
|
||||||
use DesignPatterns\More\Repository\Domain\Post;
|
use DesignPatterns\More\Repository\Domain\Post;
|
||||||
use DesignPatterns\More\Repository\Domain\PostId;
|
use DesignPatterns\More\Repository\Domain\PostId;
|
||||||
|
|
||||||
@@ -16,10 +17,7 @@ use DesignPatterns\More\Repository\Domain\PostId;
|
|||||||
*/
|
*/
|
||||||
class PostRepository
|
class PostRepository
|
||||||
{
|
{
|
||||||
/**
|
private Persistence $persistence;
|
||||||
* @var Persistence
|
|
||||||
*/
|
|
||||||
private $persistence;
|
|
||||||
|
|
||||||
public function __construct(Persistence $persistence)
|
public function __construct(Persistence $persistence)
|
||||||
{
|
{
|
||||||
@@ -35,8 +33,8 @@ class PostRepository
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$arrayData = $this->persistence->retrieve($id->toInt());
|
$arrayData = $this->persistence->retrieve($id->toInt());
|
||||||
} catch (\OutOfBoundsException $e) {
|
} catch (OutOfBoundsException $e) {
|
||||||
throw new \OutOfBoundsException(sprintf('Post with id %d does not exist', $id->toInt()), 0, $e);
|
throw new OutOfBoundsException(sprintf('Post with id %d does not exist', $id->toInt()), 0, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Post::fromState($arrayData);
|
return Post::fromState($arrayData);
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\Repository\Tests;
|
namespace DesignPatterns\More\Repository\Tests;
|
||||||
|
|
||||||
|
use OutOfBoundsException;
|
||||||
use DesignPatterns\More\Repository\Domain\PostId;
|
use DesignPatterns\More\Repository\Domain\PostId;
|
||||||
use DesignPatterns\More\Repository\Domain\PostStatus;
|
use DesignPatterns\More\Repository\Domain\PostStatus;
|
||||||
use DesignPatterns\More\Repository\InMemoryPersistence;
|
use DesignPatterns\More\Repository\InMemoryPersistence;
|
||||||
@@ -11,10 +12,7 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
class PostRepositoryTest extends TestCase
|
class PostRepositoryTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
private PostRepository $repository;
|
||||||
* @var PostRepository
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
@@ -28,7 +26,7 @@ class PostRepositoryTest extends TestCase
|
|||||||
|
|
||||||
public function testThrowsExceptionWhenTryingToFindPostWhichDoesNotExist()
|
public function testThrowsExceptionWhenTryingToFindPostWhichDoesNotExist()
|
||||||
{
|
{
|
||||||
$this->expectException(\OutOfBoundsException::class);
|
$this->expectException(OutOfBoundsException::class);
|
||||||
$this->expectExceptionMessage('Post with id 42 does not exist');
|
$this->expectExceptionMessage('Post with id 42 does not exist');
|
||||||
|
|
||||||
$this->repository->findById(PostId::fromInt(42));
|
$this->repository->findById(PostId::fromInt(42));
|
||||||
|
@@ -2,17 +2,20 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\More\ServiceLocator;
|
namespace DesignPatterns\More\ServiceLocator;
|
||||||
|
|
||||||
|
use OutOfRangeException;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class ServiceLocator
|
class ServiceLocator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string[][]
|
* @var string[][]
|
||||||
*/
|
*/
|
||||||
private $services = [];
|
private array $services = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Service[]
|
* @var Service[]
|
||||||
*/
|
*/
|
||||||
private $instantiated = [];
|
private array $instantiated = [];
|
||||||
|
|
||||||
public function addInstance(string $class, Service $service)
|
public function addInstance(string $class, Service $service)
|
||||||
{
|
{
|
||||||
@@ -51,11 +54,11 @@ class ServiceLocator
|
|||||||
$object = new $class($args[0], $args[1], $args[2]);
|
$object = new $class($args[0], $args[1], $args[2]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new \OutOfRangeException('Too many arguments given');
|
throw new OutOfRangeException('Too many arguments given');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$object instanceof Service) {
|
if (!$object instanceof Service) {
|
||||||
throw new \InvalidArgumentException('Could not register service: is no instance of Service');
|
throw new InvalidArgumentException('Could not register service: is no instance of Service');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->instantiated[$class] = $object;
|
$this->instantiated[$class] = $object;
|
||||||
|
@@ -8,10 +8,7 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
class ServiceLocatorTest extends TestCase
|
class ServiceLocatorTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
private ServiceLocator $serviceLocator;
|
||||||
* @var ServiceLocator
|
|
||||||
*/
|
|
||||||
private $serviceLocator;
|
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
|
@@ -8,14 +8,8 @@ namespace DesignPatterns\Structural\Adapter;
|
|||||||
*/
|
*/
|
||||||
class EBookAdapter implements Book
|
class EBookAdapter implements Book
|
||||||
{
|
{
|
||||||
/**
|
protected EBook $eBook;
|
||||||
* @var EBook
|
|
||||||
*/
|
|
||||||
protected $eBook;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param EBook $eBook
|
|
||||||
*/
|
|
||||||
public function __construct(EBook $eBook)
|
public function __construct(EBook $eBook)
|
||||||
{
|
{
|
||||||
$this->eBook = $eBook;
|
$this->eBook = $eBook;
|
||||||
@@ -37,8 +31,6 @@ class EBookAdapter implements Book
|
|||||||
/**
|
/**
|
||||||
* notice the adapted behavior here: EBook::getPage() will return two integers, but Book
|
* notice the adapted behavior here: EBook::getPage() will return two integers, but Book
|
||||||
* supports only a current page getter, so we adapt the behavior here
|
* supports only a current page getter, so we adapt the behavior here
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getPage(): int
|
public function getPage(): int
|
||||||
{
|
{
|
||||||
|
@@ -8,15 +8,8 @@ namespace DesignPatterns\Structural\Adapter;
|
|||||||
*/
|
*/
|
||||||
class Kindle implements EBook
|
class Kindle implements EBook
|
||||||
{
|
{
|
||||||
/**
|
private int $page = 1;
|
||||||
* @var int
|
private int $totalPages = 100;
|
||||||
*/
|
|
||||||
private $page = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $totalPages = 100;
|
|
||||||
|
|
||||||
public function pressNext()
|
public function pressNext()
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Adapter;
|
|||||||
|
|
||||||
class PaperBook implements Book
|
class PaperBook implements Book
|
||||||
{
|
{
|
||||||
/**
|
private int $page;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $page;
|
|
||||||
|
|
||||||
public function open()
|
public function open()
|
||||||
{
|
{
|
||||||
|
@@ -4,22 +4,13 @@ namespace DesignPatterns\Structural\Bridge;
|
|||||||
|
|
||||||
abstract class Service
|
abstract class Service
|
||||||
{
|
{
|
||||||
/**
|
protected Formatter $implementation;
|
||||||
* @var Formatter
|
|
||||||
*/
|
|
||||||
protected $implementation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Formatter $printer
|
|
||||||
*/
|
|
||||||
public function __construct(Formatter $printer)
|
public function __construct(Formatter $printer)
|
||||||
{
|
{
|
||||||
$this->implementation = $printer;
|
$this->implementation = $printer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Formatter $printer
|
|
||||||
*/
|
|
||||||
public function setImplementation(Formatter $printer)
|
public function setImplementation(Formatter $printer)
|
||||||
{
|
{
|
||||||
$this->implementation = $printer;
|
$this->implementation = $printer;
|
||||||
|
@@ -11,15 +11,13 @@ class Form implements Renderable
|
|||||||
/**
|
/**
|
||||||
* @var Renderable[]
|
* @var Renderable[]
|
||||||
*/
|
*/
|
||||||
private $elements;
|
private array $elements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* runs through all elements and calls render() on them, then returns the complete representation
|
* runs through all elements and calls render() on them, then returns the complete representation
|
||||||
* of the form.
|
* of the form.
|
||||||
*
|
*
|
||||||
* from the outside, one will not see this and the form will act like a single object instance
|
* from the outside, one will not see this and the form will act like a single object instance
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
@@ -34,9 +32,6 @@ class Form implements Renderable
|
|||||||
return $formCode;
|
return $formCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Renderable $element
|
|
||||||
*/
|
|
||||||
public function addElement(Renderable $element)
|
public function addElement(Renderable $element)
|
||||||
{
|
{
|
||||||
$this->elements[] = $element;
|
$this->elements[] = $element;
|
||||||
|
@@ -2,19 +2,21 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\Composite\Tests;
|
namespace DesignPatterns\Structural\Composite\Tests;
|
||||||
|
|
||||||
use DesignPatterns\Structural\Composite;
|
use DesignPatterns\Structural\Composite\Form;
|
||||||
|
use DesignPatterns\Structural\Composite\TextElement;
|
||||||
|
use DesignPatterns\Structural\Composite\InputElement;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class CompositeTest extends TestCase
|
class CompositeTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testRender()
|
public function testRender()
|
||||||
{
|
{
|
||||||
$form = new Composite\Form();
|
$form = new Form();
|
||||||
$form->addElement(new Composite\TextElement('Email:'));
|
$form->addElement(new TextElement('Email:'));
|
||||||
$form->addElement(new Composite\InputElement());
|
$form->addElement(new InputElement());
|
||||||
$embed = new Composite\Form();
|
$embed = new Form();
|
||||||
$embed->addElement(new Composite\TextElement('Password:'));
|
$embed->addElement(new TextElement('Password:'));
|
||||||
$embed->addElement(new Composite\InputElement());
|
$embed->addElement(new InputElement());
|
||||||
$form->addElement($embed);
|
$form->addElement($embed);
|
||||||
|
|
||||||
// This is just an example, in a real world scenario it is important to remember that web browsers do not
|
// This is just an example, in a real world scenario it is important to remember that web browsers do not
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Composite;
|
|||||||
|
|
||||||
class TextElement implements Renderable
|
class TextElement implements Renderable
|
||||||
{
|
{
|
||||||
/**
|
private string $text;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $text;
|
|
||||||
|
|
||||||
public function __construct(string $text)
|
public function __construct(string $text)
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\DataMapper;
|
|||||||
|
|
||||||
class StorageAdapter
|
class StorageAdapter
|
||||||
{
|
{
|
||||||
/**
|
private array $data = [];
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $data = [];
|
|
||||||
|
|
||||||
public function __construct(array $data)
|
public function __construct(array $data)
|
||||||
{
|
{
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\DataMapper\Tests;
|
namespace DesignPatterns\Structural\DataMapper\Tests;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
use DesignPatterns\Structural\DataMapper\StorageAdapter;
|
use DesignPatterns\Structural\DataMapper\StorageAdapter;
|
||||||
use DesignPatterns\Structural\DataMapper\User;
|
use DesignPatterns\Structural\DataMapper\User;
|
||||||
use DesignPatterns\Structural\DataMapper\UserMapper;
|
use DesignPatterns\Structural\DataMapper\UserMapper;
|
||||||
@@ -21,7 +22,7 @@ class DataMapperTest extends TestCase
|
|||||||
|
|
||||||
public function testWillNotMapInvalidData()
|
public function testWillNotMapInvalidData()
|
||||||
{
|
{
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
$storage = new StorageAdapter([]);
|
$storage = new StorageAdapter([]);
|
||||||
$mapper = new UserMapper($storage);
|
$mapper = new UserMapper($storage);
|
||||||
|
@@ -4,15 +4,8 @@ namespace DesignPatterns\Structural\DataMapper;
|
|||||||
|
|
||||||
class User
|
class User
|
||||||
{
|
{
|
||||||
/**
|
private string $username;
|
||||||
* @var string
|
private string $email;
|
||||||
*/
|
|
||||||
private $username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $email;
|
|
||||||
|
|
||||||
public static function fromState(array $state): User
|
public static function fromState(array $state): User
|
||||||
{
|
{
|
||||||
@@ -32,18 +25,12 @@ class User
|
|||||||
$this->email = $email;
|
$this->email = $email;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getUsername(): string
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getUsername()
|
|
||||||
{
|
{
|
||||||
return $this->username;
|
return $this->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getEmail(): string
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getEmail()
|
|
||||||
{
|
{
|
||||||
return $this->email;
|
return $this->email;
|
||||||
}
|
}
|
||||||
|
@@ -2,16 +2,12 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\DataMapper;
|
namespace DesignPatterns\Structural\DataMapper;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class UserMapper
|
class UserMapper
|
||||||
{
|
{
|
||||||
/**
|
private StorageAdapter $adapter;
|
||||||
* @var StorageAdapter
|
|
||||||
*/
|
|
||||||
private $adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param StorageAdapter $storage
|
|
||||||
*/
|
|
||||||
public function __construct(StorageAdapter $storage)
|
public function __construct(StorageAdapter $storage)
|
||||||
{
|
{
|
||||||
$this->adapter = $storage;
|
$this->adapter = $storage;
|
||||||
@@ -22,17 +18,13 @@ class UserMapper
|
|||||||
* in memory. Normally this kind of logic will be implemented using the Repository pattern.
|
* in memory. Normally this kind of logic will be implemented using the Repository pattern.
|
||||||
* However the important part is in mapRowToUser() below, that will create a business object from the
|
* However the important part is in mapRowToUser() below, that will create a business object from the
|
||||||
* data fetched from storage
|
* data fetched from storage
|
||||||
*
|
|
||||||
* @param int $id
|
|
||||||
*
|
|
||||||
* @return User
|
|
||||||
*/
|
*/
|
||||||
public function findById(int $id): User
|
public function findById(int $id): User
|
||||||
{
|
{
|
||||||
$result = $this->adapter->find($id);
|
$result = $this->adapter->find($id);
|
||||||
|
|
||||||
if ($result === null) {
|
if ($result === null) {
|
||||||
throw new \InvalidArgumentException("User #$id not found");
|
throw new InvalidArgumentException("User #$id not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->mapRowToUser($result);
|
return $this->mapRowToUser($result);
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Decorator;
|
|||||||
|
|
||||||
abstract class BookingDecorator implements Booking
|
abstract class BookingDecorator implements Booking
|
||||||
{
|
{
|
||||||
/**
|
protected Booking $booking;
|
||||||
* @var Booking
|
|
||||||
*/
|
|
||||||
protected $booking;
|
|
||||||
|
|
||||||
public function __construct(Booking $booking)
|
public function __construct(Booking $booking)
|
||||||
{
|
{
|
||||||
|
@@ -4,25 +4,10 @@ namespace DesignPatterns\Structural\DependencyInjection;
|
|||||||
|
|
||||||
class DatabaseConfiguration
|
class DatabaseConfiguration
|
||||||
{
|
{
|
||||||
/**
|
private string $host;
|
||||||
* @var string
|
private int $port;
|
||||||
*/
|
private string $username;
|
||||||
private $host;
|
private string $password;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $port;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $password;
|
|
||||||
|
|
||||||
public function __construct(string $host, int $port, string $username, string $password)
|
public function __construct(string $host, int $port, string $username, string $password)
|
||||||
{
|
{
|
||||||
|
@@ -4,14 +4,8 @@ namespace DesignPatterns\Structural\DependencyInjection;
|
|||||||
|
|
||||||
class DatabaseConnection
|
class DatabaseConnection
|
||||||
{
|
{
|
||||||
/**
|
private DatabaseConfiguration $configuration;
|
||||||
* @var DatabaseConfiguration
|
|
||||||
*/
|
|
||||||
private $configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DatabaseConfiguration $config
|
|
||||||
*/
|
|
||||||
public function __construct(DatabaseConfiguration $config)
|
public function __construct(DatabaseConfiguration $config)
|
||||||
{
|
{
|
||||||
$this->configuration = $config;
|
$this->configuration = $config;
|
||||||
|
@@ -4,20 +4,9 @@ namespace DesignPatterns\Structural\Facade;
|
|||||||
|
|
||||||
class Facade
|
class Facade
|
||||||
{
|
{
|
||||||
/**
|
private OperatingSystem $os;
|
||||||
* @var OperatingSystem
|
private Bios $bios;
|
||||||
*/
|
|
||||||
private $os;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Bios
|
|
||||||
*/
|
|
||||||
private $bios;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Bios $bios
|
|
||||||
* @param OperatingSystem $os
|
|
||||||
*/
|
|
||||||
public function __construct(Bios $bios, OperatingSystem $os)
|
public function __construct(Bios $bios, OperatingSystem $os)
|
||||||
{
|
{
|
||||||
$this->bios = $bios;
|
$this->bios = $bios;
|
||||||
|
@@ -4,20 +4,9 @@ namespace DesignPatterns\Structural\FluentInterface;
|
|||||||
|
|
||||||
class Sql
|
class Sql
|
||||||
{
|
{
|
||||||
/**
|
private array $fields = [];
|
||||||
* @var array
|
private array $from = [];
|
||||||
*/
|
private array $where = [];
|
||||||
private $fields = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $from = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $where = [];
|
|
||||||
|
|
||||||
public function select(array $fields): Sql
|
public function select(array $fields): Sql
|
||||||
{
|
{
|
||||||
|
@@ -11,10 +11,8 @@ class Character implements Text
|
|||||||
/**
|
/**
|
||||||
* Any state stored by the concrete flyweight must be independent of its context.
|
* Any state stored by the concrete flyweight must be independent of its context.
|
||||||
* For flyweights representing characters, this is usually the corresponding character code.
|
* For flyweights representing characters, this is usually the corresponding character code.
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
private $name;
|
private string $name;
|
||||||
|
|
||||||
public function __construct(string $name)
|
public function __construct(string $name)
|
||||||
{
|
{
|
||||||
|
@@ -7,9 +7,10 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
class FlyweightTest extends TestCase
|
class FlyweightTest extends TestCase
|
||||||
{
|
{
|
||||||
private $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
private array $characters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
|
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
|
||||||
private $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica'];
|
|
||||||
|
private array $fonts = ['Arial', 'Times New Roman', 'Verdana', 'Helvetica'];
|
||||||
|
|
||||||
public function testFlyweight()
|
public function testFlyweight()
|
||||||
{
|
{
|
||||||
|
@@ -2,16 +2,18 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\Flyweight;
|
namespace DesignPatterns\Structural\Flyweight;
|
||||||
|
|
||||||
|
use Countable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory manages shared flyweights. Clients should not instantiate them directly,
|
* A factory manages shared flyweights. Clients should not instantiate them directly,
|
||||||
* but let the factory take care of returning existing objects or creating new ones.
|
* but let the factory take care of returning existing objects or creating new ones.
|
||||||
*/
|
*/
|
||||||
class TextFactory implements \Countable
|
class TextFactory implements Countable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Text[]
|
* @var Text[]
|
||||||
*/
|
*/
|
||||||
private $charPool = [];
|
private array $charPool = [];
|
||||||
|
|
||||||
public function get(string $name): Text
|
public function get(string $name): Text
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Flyweight;
|
|||||||
|
|
||||||
class Word implements Text
|
class Word implements Text
|
||||||
{
|
{
|
||||||
/**
|
private string $name;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function __construct(string $name)
|
public function __construct(string $name)
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,7 @@ namespace DesignPatterns\Structural\Proxy;
|
|||||||
|
|
||||||
class BankAccountProxy extends HeavyBankAccount implements BankAccount
|
class BankAccountProxy extends HeavyBankAccount implements BankAccount
|
||||||
{
|
{
|
||||||
/**
|
private ?int $balance = null;
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $balance;
|
|
||||||
|
|
||||||
public function getBalance(): int
|
public function getBalance(): int
|
||||||
{
|
{
|
||||||
|
@@ -7,7 +7,7 @@ class HeavyBankAccount implements BankAccount
|
|||||||
/**
|
/**
|
||||||
* @var int[]
|
* @var int[]
|
||||||
*/
|
*/
|
||||||
private $transactions = [];
|
private array $transactions = [];
|
||||||
|
|
||||||
public function deposit(int $amount)
|
public function deposit(int $amount)
|
||||||
{
|
{
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\Registry;
|
namespace DesignPatterns\Structural\Registry;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
abstract class Registry
|
abstract class Registry
|
||||||
{
|
{
|
||||||
const LOGGER = 'logger';
|
const LOGGER = 'logger';
|
||||||
@@ -12,19 +14,16 @@ abstract class Registry
|
|||||||
*
|
*
|
||||||
* @var Service[]
|
* @var Service[]
|
||||||
*/
|
*/
|
||||||
private static $services = [];
|
private static array $services = [];
|
||||||
|
|
||||||
/**
|
private static array $allowedKeys = [
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private static $allowedKeys = [
|
|
||||||
self::LOGGER,
|
self::LOGGER,
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function set(string $key, Service $value)
|
public static function set(string $key, Service $value)
|
||||||
{
|
{
|
||||||
if (!in_array($key, self::$allowedKeys)) {
|
if (!in_array($key, self::$allowedKeys)) {
|
||||||
throw new \InvalidArgumentException('Invalid key given');
|
throw new InvalidArgumentException('Invalid key given');
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$services[$key] = $value;
|
self::$services[$key] = $value;
|
||||||
@@ -33,7 +32,7 @@ abstract class Registry
|
|||||||
public static function get(string $key): Service
|
public static function get(string $key): Service
|
||||||
{
|
{
|
||||||
if (!in_array($key, self::$allowedKeys) || !isset(self::$services[$key])) {
|
if (!in_array($key, self::$allowedKeys) || !isset(self::$services[$key])) {
|
||||||
throw new \InvalidArgumentException('Invalid key given');
|
throw new InvalidArgumentException('Invalid key given');
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$services[$key];
|
return self::$services[$key];
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace DesignPatterns\Structural\Registry\Tests;
|
namespace DesignPatterns\Structural\Registry\Tests;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
use DesignPatterns\Structural\Registry\Registry;
|
use DesignPatterns\Structural\Registry\Registry;
|
||||||
use DesignPatterns\Structural\Registry\Service;
|
use DesignPatterns\Structural\Registry\Service;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
@@ -9,7 +10,10 @@ use PHPUnit\Framework\TestCase;
|
|||||||
|
|
||||||
class RegistryTest extends TestCase
|
class RegistryTest extends TestCase
|
||||||
{
|
{
|
||||||
private $service;
|
/**
|
||||||
|
* @var Service
|
||||||
|
*/
|
||||||
|
private MockObject $service;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
@@ -18,7 +22,6 @@ class RegistryTest extends TestCase
|
|||||||
|
|
||||||
public function testSetAndGetLogger()
|
public function testSetAndGetLogger()
|
||||||
{
|
{
|
||||||
/** @noinspection PhpParamsInspection */
|
|
||||||
Registry::set(Registry::LOGGER, $this->service);
|
Registry::set(Registry::LOGGER, $this->service);
|
||||||
|
|
||||||
$this->assertSame($this->service, Registry::get(Registry::LOGGER));
|
$this->assertSame($this->service, Registry::get(Registry::LOGGER));
|
||||||
@@ -26,7 +29,7 @@ class RegistryTest extends TestCase
|
|||||||
|
|
||||||
public function testThrowsExceptionWhenTryingToSetInvalidKey()
|
public function testThrowsExceptionWhenTryingToSetInvalidKey()
|
||||||
{
|
{
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
Registry::set('foobar', $this->service);
|
Registry::set('foobar', $this->service);
|
||||||
}
|
}
|
||||||
@@ -40,7 +43,7 @@ class RegistryTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testThrowsExceptionWhenTryingToGetNotSetKey()
|
public function testThrowsExceptionWhenTryingToGetNotSetKey()
|
||||||
{
|
{
|
||||||
$this->expectException(\InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
|
||||||
Registry::get(Registry::LOGGER);
|
Registry::get(Registry::LOGGER);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "domnikl/design-patterns-php",
|
"name": "domnikl/design-patterns-php",
|
||||||
"description": "Sample code for several design patterns in PHP",
|
"description": "Sample code for several design patterns in PHP",
|
||||||
|
"license": ["MIT"],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Dominik Liebler",
|
"name": "Dominik Liebler",
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
],
|
],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.2",
|
"php": ">=7.4",
|
||||||
"psr/http-message": "^1.0",
|
"psr/http-message": "^1.0",
|
||||||
"ext-json": "*"
|
"ext-json": "*"
|
||||||
},
|
},
|
||||||
@@ -18,11 +19,10 @@
|
|||||||
"squizlabs/php_codesniffer": "^3",
|
"squizlabs/php_codesniffer": "^3",
|
||||||
"flyeralarm/php-code-validator": "^2.2",
|
"flyeralarm/php-code-validator": "^2.2",
|
||||||
"vimeo/psalm": "^3.4",
|
"vimeo/psalm": "^3.4",
|
||||||
"psalm/plugin-phpunit": "^0.7.0"
|
"psalm/plugin-phpunit": "^0.7.0",
|
||||||
|
"rector/rector": "^0.6.1"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"classmap": ["Behavioral", "Creational", "Structural", "More"]
|
||||||
"DesignPatterns\\": ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2388
composer.lock
generated
2388
composer.lock
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user