Skip to content

Instantly share code, notes, and snippets.

@cangelis
Last active June 21, 2023 02:03
Show Gist options
  • Save cangelis/1442951 to your computer and use it in GitHub Desktop.
Save cangelis/1442951 to your computer and use it in GitHub Desktop.
A simple Command Pattern implementation (Calculator example) on PHP
<?php
abstract class Command {
abstract public function unExecute ();
abstract public function Execute ();
}
class concreteCommand extends Command {
private $operator,$operand,$calculator;
public function __construct ($calculator,$operator,$operand) {
$this->operator = $operator;
$this->operand = $operand;
$this->calculator = $calculator;
}
public function Execute() {
$this->calculator->Action($this->operator,$this->operand);
}
public function unExecute () {
$this->calculator->Action($this->Undo($this->operator),$this->operand);
}
private function Undo ($operator) {
switch ($operator) {
case '+': return '-';
case '-': return '+';
case '*': return '/';
case '/': return '*';
}
}
}
class Calculator {
private $current;
public function __construct() {
$this->current = 0;
}
public function Action($operator,$operand) {
switch ($operator) {
case '+':
$this->current += $operand;
break;
case '-':
$this->current -= $operand;
break;
case '*':
$this->current *= $operand;
break;
case '/':
$this->current /= $operand;
break;
}
}
public function getCurrent() {
return $this->current;
}
}
class Invoker {
private $commands,$calculator,$current;
public function __construct() {
$this->current =-1;
}
public function Undo() {
if ($this->current >= 0) {
$this->commands[$this->current]->unExecute();
$this->current--;
}
}
public function Compute($command) {
$command->Execute();
$this->current++;
$this->commands[$this->current] = $command;
}
}
?>
This is a simple Command Pattern example which performs Undo operation on a calculator. You may use callbacks in order to verify open-close principle.
UML Diagram: http://en.wikipedia.org/wiki/File:Command_Design_Pattern_Class_Diagram.png
Our receiver here is calculator.
<?php
$User = new Invoker();
$calculator = new Calculator();
$command = new concreteCommand($calculator,'+',5);
$User->Compute($command);
echo "After +5: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'*',7);
$User->Compute($command);
echo "After *7: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'/',2);
$User->Compute($command);
echo "After /2: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'-',10);
$User->Compute($command);
echo "After -10: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo "Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo "Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo "Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo "Undo Operation: ".$calculator->getCurrent()."<br/>";
?>
@xwlee
Copy link

xwlee commented Jan 5, 2013

Inside Invoker class constructor, the code should be
$this->current = -1

@cangelis
Copy link
Author

cangelis commented Mar 1, 2013

Thank you. fixed.

@stefgosselin
Copy link

This is actually one of the best examples I've come across. Thanks for sharing friend.

@Potherca
Copy link

Potherca commented Aug 8, 2017

To save people an extra click, this is the UML image:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment