Я написал код, который состоит из набора объектов, которые реализуют простой интерфейс. Эти объекты являются просто DTO. Они должны быть представлены. Каждый из них требует собственного рендеринга. Первоначально я думаю, что ОК, так что будет интерфейс визуализации, который имеет один метод render
и он примет результат ResultInterface
. Каждый элемент результата имеет разные части дополнительных данных, которые необходимо визуализировать.Проектирование системы рендеринга объекта
Так что на самом деле происходит то, что каждый обработчик затем проверяет, получает ли он правильный тип. Поэтому, хотя кажется, что он принимает что-либо, реализующее ResultInterface
, на самом деле это не так. Тогда я думаю, ну почему я даже беспокоюсь о типе намекаю на ResultInterface
.
Вот несколько примеров, иллюстрирующих:
<?php
Interface RendererInterface
{
public function render(ResultInterface $result);
}
class ExceptionFailureRenderer implements RendererInterface
{
public function render(ResultInterface $result)
{
if (!$result instanceof ExceptionFailure) {
throw new InvalidArgumentException;
}
}
}
class SomeOtherFailureRenderer implements RendererInterface
{
public function render(ResultInterface $result)
{
if (!$result instanceof SomeOtherFailure) {
throw new InvalidArgumentException;
}
}
}
Interface ResultInterface
{
public function getName();
}
class ExceptionFailure implements ResultInterface
{
public function getName()
{
return 'Exception Failure';
}
public function getException()
{
return $this->exception;
}
}
class SomeOtherFailure implements ResultInterface
{
public function getName()
{
return 'Some Other Failure';
}
public function getSomeOtherPieceOfData()
{
return $this->importantData;
}
}
$renderers = [
ExceptionFailure::class => new ExceptionFailureRenderer,
SomeOtherFailure::class => new SomeOtherFailureRenderer
];
$output = '';
foreach ($results as $result) {
$renderer = $renderers[get_class($result)];
$output .= $renderers->render($result);
}
Вопрос
Как это могло быть разработаны лучше избегать вызова конкретных методов, когда Renderer
только ожидает ResultInterface
?
Спасибо, это имеет больше смысла. Немногие: не делает ли это '' __construct' частью контракта 'RendererInterface' сейчас? Что делать, если у рендереров больше и разных зависимостей? Наконец, рендеринги теперь содержат, казалось бы, ненужное состояние. Я согласен с тем, что конкретные интерфейсы для каждого результата кажутся излишними, так как у меня много разных результатов в системе. –
hello @AydinHassan Чтобы ответить на ваши вопросы в обратном порядке, нет ничего выше явно добавленного состояния. Возьмем, например, «ExceptionFailureRenderer» - любой экземпляр должен содержать один экземпляр «ExceptionFailure», это не может быть изменено, другого состояния нет - объект неизменен. Конечно, вы можете изменить это, добавив методы, которые его изменяют (например, сеттер), но мой код не содержит никаких действий. – Steve
Что касается 'RendererInterface', конструктор не является частью контракта. Интерфейс просто гарантирует, что любой объект, который его реализует, содержит открытый, без параметров метод с именем «render». Любой объект, зависящий от экземпляра 'RendererInterface', просто ожидает, что ему будет дан такой объект, он не знает и не заботится о том, как он построен. Конечно, любая конкретная реализация 'RenderFactoryInterface' ** будет ** знать, как построить различные типы, но это ожидалось. – Steve