Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP version of Visitor pattern
<?php
/**
* Интерфейс для посещаемого
* Посещаемые объекты должны реализовывать
* - метод accept - принятие посетителя
* - метод getTotalCount - получение общей суммы чего-либо
*
*/
interface IDlvVisitee
{
public function accept(IDeliveryVisistor $visitor);
public function getTotalCount();
}
/**
* Три конкретных реализации посещаемых объектов
* В данном случае это некие гипотетические службы
* доставки, позволяющие рассчитать стоимость
* доставки для каждой из них.
*/
class Dlv1 implements IDlvVisitee
{
private $data;
public function __construct($params)
{
$this->data = $params;
}
public function getTotalCount()
{
return __CLASS__ . ' of TOTAL!';
}
public function accept(IDeliveryVisistor $visitor)
{
return $visitor->visit($this);
}
}
class Dlv2 implements IDlvVisitee
{
private $data;
public function __construct($params)
{
$this->data = $params;
}
public function getTotalCount()
{
return __CLASS__ . ' of TOTAL!';
}
public function accept(IDeliveryVisistor $visitor)
{
return $visitor->visit($this);
}
}
class Dlv3 implements IDlvVisitee
{
private $data;
public function __construct($params)
{
$this->data = $params;
}
public function getTotalCount()
{
return __CLASS__ . ' of TOTAL!';
}
public function accept(IDeliveryVisistor $visitor)
{
return $visitor->visit($this);
}
}
/**
* Интерфейс посетителя
* Объект посетителя должен поддерживать метод visit
* в который передается посещаемый объект.
* В данном случае необходимо чтобы посещаемый
* объект расширял интерфейс IDlvVisitee
*/
interface IDeliveryVisistor {
public function visit(IDlvVisitee $visitee);
}
/**
* Реализация простого посетителя
* С полученного объекта $visitee
* вызывается метод getTotalCount()
* возвращающий необходимые данные
*/
class DeliveryVisitor implements IDeliveryVisistor
{
public function __construct()
{
}
/**
* На самом деле не совсем тру, ибо
* мы все-таки заставляем $visitee
* что-то реализовывать самостоятельно
* а по идее этого быть не должно.
* Мы должны просто получать свойства
* объекта и группировать их как
* надо конкретному посетителю
*
*/
public function visit(IDlvVisitee $visitee)
{
echo'<pre>',print_r($visitee),'</pre>'; // TODO
return $visitee->getTotalCount();
}
}
/* Пример */
/* Создаем набор доставок */
$deliveries_pool = array(
new Dlv1,
new Dlv2,
new Dlv3,
);
echo'<pre>Pool files: ',print_r($deliveries_pool),'</pre>';
echo'<hr />';
/* Создаем посетителя */
$visitor = new DeliveryVisitor;
echo'<pre>',print_r($visitor),'</pre>';
echo'<hr />';
/* Посещаем все доставки и получаем отдаваемые ими данные */
$results = [];
foreach ($deliveries_pool as $dlv) {
$results[] = $dlv->accept($visitor);
}
echo'<hr />';
echo'<pre>$results: ',print_r($results),'</pre>';
die('Dead in ' . __FILE__ . ' on line '. __LINE__ . PHP_EOL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment