Skip to content

Instantly share code, notes, and snippets.

@BlackScorp
Created July 27, 2017 09:13
Show Gist options
  • Save BlackScorp/cd7956eadb2bd262c458974d9c9dd5e7 to your computer and use it in GitHub Desktop.
Save BlackScorp/cd7956eadb2bd262c458974d9c9dd5e7 to your computer and use it in GitHub Desktop.
Basic OOP Composition over inheritance example
<?php
error_reporting(-1);
ini_set('display_errors', true);
abstract class CalculatorFactory
{
public static function create($string, $value)
{
$className = ucfirst($string) . 'Calculator';
if (!class_exists($className)) {
return null;
}
return new $className($value);
}
}
trait CalculatorTrait
{
private $newValue = 0;
public function __construct($newValue)
{
if (!is_numeric($newValue)) {
$this->newValue = 0;
return;
}
$this->newValue = $newValue;
}
public function getValue()
{
return $this->newValue;
}
}
class CalculatorChain
{
private $total = 0;
private $chain = [];
/**
* @return int
*/
public function getTotal()
{
return $this->total;
}
public function add(Calculator $calculator)
{
$total = $calculator->calculate($this->total);
if ($total !== $this->total) {
$this->chain[] = $calculator;
$this->total = $total;
}
}
/**
* @return Calculator[]
*/
public function getCalculation()
{
return $this->chain;
}
public function reset()
{
$this->chain = [];
}
}
interface Calculator
{
public function calculate($lastValue);
public function getValue();
public function getSign();
}
class AddCalculator implements Calculator
{
use CalculatorTrait;
public function calculate($lastValue)
{
return $lastValue + $this->newValue;
}
public function getSign()
{
return '+';
}
}
class SubtractCalculator implements Calculator
{
use CalculatorTrait;
public function calculate($lastValue)
{
return $lastValue - $this->newValue;
}
public function getSign()
{
return '-';
}
}
class MultiplyCalculator implements Calculator
{
use CalculatorTrait;
public function calculate($lastValue)
{
return $lastValue * $this->newValue;
}
public function getSign()
{
return '*';
}
}
class DivideCalculator implements Calculator
{
use CalculatorTrait;
public function calculate($lastValue)
{
if (0 == $this->newValue) {
return 'Cannot devide by Zero';
}
return $lastValue / $this->newValue;
}
public function getSign()
{
return '/';
}
}
session_start();
$calculatorChain = new CalculatorChain();
if (isset($_SESSION['calculatorChain'])) {
$calculatorChain = $_SESSION['calculatorChain'];
}
$value = 0;
if (isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD']) {
$value = $_POST['value'];
$calculation = isset($_GET['calculation']) ? $_GET['calculation'] : null;
$calculator = CalculatorFactory::create($calculation, $value);
if ($calculator) {
$calculatorChain->add($calculator);
}
if (isset($_GET['result'])) {
$calculatorChain->reset();
$value = 0;
}
}
$_SESSION['calculatorChain'] = $calculatorChain;
header('Content-Type:text/html;charset=utf-8');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Calculator</title>
<meta charset="UTF-8"/>
</head>
<body>
<fieldset>
<legend>Output</legend>
<div>
<small><?php foreach ($calculatorChain->getCalculation() as $calculation): ?>
<?= $calculation->getValue() ?> <?= $calculation->getSign() ?>
<?php endforeach; ?>
</small>
<div><?= $calculatorChain->getTotal() ?></div>
</div>
</fieldset>
<fieldset>
<legend>Calculator</legend>
<form method="POST">
<label>
Value: <input name="value" value="<?= $value ?>"/>
</label>
<button name="action" formaction="?calculation=add">+</button>
<button name="action" formaction="?calculation=subtract">-</button>
<button name="action" formaction="?calculation=multiply">*</button>
<button name="action" formaction="?calculation=divide">/</button>
<button name="action" formaction="?result">=</button>
</form>
</fieldset>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment