cubiche / visitor
Visitor library
dev-master
2017-03-16 11:29 UTC
Requires
- php: ^5.5.9|^7.0
Requires (Dev)
- cubiche/tests: dev-master
This package is auto-updated.
Last update: 2024-12-04 23:53:03 UTC
README
A visitor pattern implementation in PHP, using a Dynamic dispatch mechanism.
Installation
Via Composer
$ composer require cubiche/visitor:dev-master
Basic usage
Arithmetic expressions calculator
use Cubiche\Core\Visitor\Visitee; use Cubiche\Core\Visitor\Visitor; abstract class Expression extends Visitee {} abstract class Operator extends Expression { protected $operator; protected $firstOperand; protected $secondOperand; public function __construct($operator, Expression $firstOperand, Expression $secondOperand) { $this->operator = $operator; $this->firstOperand = $firstOperand; $this->secondOperand = $secondOperand; } public function operator() { return $this->operator; } public function firstOperand() { return $this->firstOperand; } public function secondOperand() { return $this->secondOperand; } } class Sum extends Operator { public function __construct(Expression $firstOperand, Expression $secondOperand) { parent::__construct('+', $firstOperand, $secondOperand); } } class Mult extends Operator { public function __construct(Expression $firstOperand, Expression $secondOperand) { parent::__construct('*', $firstOperand, $secondOperand); } } class Value extends Expression { protected $value; public function __construct($value) { $this->value = $value; } public function value() { return $this->value; } } class Variable extends Expression { protected $name; public function __construct($name) { $this->name = $name; } public function name() { return $this->name; } } class Calculator extends Visitor { public function visitSum(Sum $sum) { return $sum->firstOperand()->accept($this) + $sum->secondOperand()->accept($this); } public function visitMult(Mult $mult) { return $mult->firstOperand()->accept($this) * $mult->secondOperand()->accept($this); } public function visitValue(Value $value) { return $value->value(); } } $expression = new Sum( new Value(5), new Mult( new Value(3), new Value(2) ) ); $calculator = new Calculator(); $result = $expression->accept($calculator);
Visit parent class
use Cubiche\Core\Visitor\Visitor; class ExpressionToStringConverter extends Visitor { public function visitOperator(Operator $op) { return '('.$op->firstOperand()->accept($this).$op->operator().$op->secondOperand()->accept($this).')'; } public function visitValue(Value $value) { return (string) $value->value(); } public function visitVariable(Variable $variable) { return $variable->name(); } } $expression = new Sum( new Value(5), new Mult( new Value(3), new Value(2) ) ); $converter = new ExpressionToStringConverter(); echo $expression->accept($converter);
Note that the visitOperator
method is invoked when an operator(Sum
or Mult
) is visited.
Passing parameters to visit methods
class SmartExpressionToStringConverter extends ExpressionToStringConverter { public function visitOperator(Operator $op, $parentOperator = null) { $currentOperator = $op->operator(); $expression = $op->firstOperand()->accept($this, $currentOperator). $currentOperator.$op->secondOperand()->accept($this, $currentOperator); return $this->requireParentheses($currentOperator, $parentOperator) ? '('.$expression.')' : $expression; } protected function requireParentheses($currentOperator, $parentOperator) { return $currentOperator === '+' && $parentOperator === '*'; } } $expression = new Sum( new Value(5), new Mult( new Value(3), new Value(2) ) ); $converter = new SmartExpressionToStringConverter(); echo $expression->accept($converter);
Extending another visitor without inheritance
use Cubiche\Core\Visitor\LinkedVisitor; class Evaluator extends LinkedVisitor { protected $variables; public function __construct(Calculator $calculator, $variables = array()) { parent::__construct($calculator); $this->variables = $variables; } public function visitVariable(Variable $variable) { if (isset($this->variables[$variable->name()])) { return $this->variables[$variable->name()]; } throw new \Exception(\sprintf("Unknown variable '%s'", $variable->name())); } } $expression = new Mult( new Variable('x'), new Sum( new Value(5), new Mult( new Variable('y'), new Value(2) ) ) ); $variables = array('x' => 10, 'y' => -7); $evaluator = new Evaluator(new Calculator(), $variables); $converter = new SmartExpressionToStringConverter(); echo $expression->accept($converter).' = '.$expression->accept($evaluator).PHP_EOL;
Note that the Evaluator
can only visit the Variable
instances and delegate in Calculator
the others expressions.