class SimplePrinter implements Printer
{
public function print(Circle $shape) {}
public function print(Rectangle $shape) {}
public function print(Square $shape) {}
}
class SimplePrinter implements Printer
{
public function print(Shape $shape)
{
$shapePrinter = [
Circle::class => [$this, 'printCircle'],
Rectangle::class => [$this, 'printRectangle'],
printSquare::class => [$this, 'printSquare'],
][get_class($shape)] ?? null;
if (null === $shapePrinter) {
// throw exception
}
$shapePrinter($shape);
}
private function printCircle(Circle $shape) {}
private function printRectangle(Rectangle $shape) {}
private function printSquare(Square $shape) {}
}
interface Printer
{
public function printRectangle(Rectangle $shape);
public function printCircle(Rectangle $shape);
// ...
}
abstract class Shape
{
abstract public function print(Printer $printer);
}
class Rectangle extends Shape
{
public function print(Printer $printer)
{
$printer->printRectangle($this);
}
}
interface Printer
{
public function supports(Shape $shape);
public function print(Shape $shape);
}
class DefaultPrinter implements Printer
{
private $printers;
public function __construct(array $printers) { $this->printers = $printers; }
public function supports(Shape $shape) { return true; }
public function print(Shape $shape)
{
foreach ($this->printers as $printer) {
if ($printer->supports($shape)) {
return $printer->print($shape);
}
}
}
}
class CircleDefaultPrinter implements Printer
{
public function supports(Shape $shape)
{
return $shape instanceof Circle;
}
public function print(Shape $shape)
{
// ...
}
}
printer = Dispatch();
printer.add_call((Circle), default_circle_printer)
printer.add_call((Rectangle), default_rectangle_printer)
printer(shape) // multiple dispatch
Но мне это будет труднее спрогнозировать струтуры например тех же JSON объектов на выходе если у меня ещё нет кода.
В вашем примере вы называете переопределение метода перегрузкой, а вызов метода переданного класса в методе иного класса - double dispatch'ем, что достаточно далеко от их определений.
Зачем? Можно так сделать, но не вижу ничего плохого, если есть ряд методов, связанных одной задачей.
Хендлеры делают разные вещи, это, так сказать, источник проблемы.
Проблема на высоком уровне такова:
Есть такая штука - культ карго. Вот вы сейчас описали это поведение человека.
Нет конечно, не стоит в крайности впадать. Просто нужно понимать что когда юзать. Например возьмем ту же Doctrine и какой-нибудь простенький проект. Например - мааахонький инстаграмчик. Пользователи постят фотки. К фоткам можно лепить лайки и комменты.
Задачи аля:
- добавить фотку
- добавить лайк
- добавить коммент
это все сводится к OLTP поскольку у нас задействовано малое количество объектов. Есть еще такой термин как агрегат сущностей, которым описывают все объекты учавствующие в бизнес транзакции. И вот ORM-ки делают это дико удобным.
Но проект развивается и вот в нашем инстраграме нужно уже отображать:
- список фоток всех друзей
- на главной странице надо отображать трендовые фотки - по одной из каждой страны
- примешивать в трендинг фотки проплаченный контент (мы ж хотим зарабатывать?)
И все это - не является задачами из разряда OLTP но доктрина предоставляет нам свой query builder и если нам не нужны потом объекты - мы можем сразу гидрировать результаты в массивчик. А можно вообще свои гидраторы сделать. А можно даже так:
то есть сразу смэпить все на какие-то промежуточные объекты которые содержат только то что нужно.
Но вот это уже не является частью непосредственно ORM - это чуть другой уровень.