I have developed a command line application which prompts the user to initially select an oven and then requests that they cook a pizza. The oven affects the pizzas cooking time. The pizzas information will be printed to the command line as well as the altered cooking time.
I wanted to use the best design principles I knew to ensure future changes were possible.
I would massively appreciate critique on:
- My actual implementation of the pattern
- Whether or not I chose a sufficient design pattern to use to fulfill a satisfactory result
- Any obvious sore-thumbs in my code
OvenFactory.php
namespace PizzaShop\Oven;
class OvenFactory
{
/**
* @var array
*/
private $ovens = [
'Gas Oven' => 'PizzaShop\Oven\GasOven',
'Stone Oven' => 'PizzaShop\Oven\StoneOven',
'Hair Dryer' => 'PizzaShop\Oven\HairDryer',
];
/**
* @return array
*/
public function getOvens() {
return $this->ovens;
}
/**
* @param $name
* @return $oven
*/
public function create($name)
{
if (isset($this->ovens[$name]))
{
$oven = new $this->ovens[$name];
return $oven;
}
return null;
}
/**
* @param $name
* @return $oven
*/
public function printOven($name) {
if (isset($this->ovens[$name]))
{
$oven = $this->create($name);
print('--- ' . $oven->name . ' ---') . PHP_EOL;
$alters = 'Decreases';
if($oven->time > 0) {
$alters = 'Increases';
}
print($alters . ' cooking time by: ' . $oven->time . ' Minutes') . PHP_EOL;
return $oven;
}
return null;
}
}
StoneOven.php
<?php
namespace PizzaShop\Oven;
class StoneOven extends Oven
{
function __construct()
{
parent::setName('Stone Oven');
parent::setTime(-10);
}
}
GasOven.php
<?php
namespace PizzaShop\Oven;
class GasOven extends Oven
{
function __construct()
{
parent::setName('Gas Oven');
parent::setTime(0);
}
}
Oven.php
<?php
namespace PizzaShop\Oven;
abstract class Oven
{
/**
* @var
*/
public $time;
/**
* @var
*/
public $name;
/**
* @return mixed
*/
public function getTime() {
return $this->time;
}
/**
* @param float $time
*/
public function setTime($time)
{
$this->time = $time;
}
/**
* @return string
*/
public function getName() {
return $this->name;
}
/**
* @param $name
*/
public function setName($name) {
$this->name = $name;
}
/**
* @param $cookingtime
* @return float $time
*/
protected function getFinalTime($cookingtime) {
$oventime = $this->getTime();
if($oventime > 0) {
$time = $cookingtime + $oventime;
} else {
$time = $cookingtime - abs($oventime);
}
return $time;
}
/**
*
* @param null $pizza
*/
public function bake($pizza) {
print('*************************') . PHP_EOL;
print('--- ' . $pizza->name . ' ---') . PHP_EOL;
print('*************************') . PHP_EOL;
PHP_EOL;
print('Dough rolled out.') . PHP_EOL;
print($pizza->sauce . ' sauce spread') . PHP_EOL;
foreach ($pizza->toppings as $topping) {
print($topping . ' added.') . PHP_EOL;
}
print('Baked in ' .$this->name . ' for ' . $this->getFinalTime($pizza->defaulttime) . ' minutes') . PHP_EOL;
return;
}
}
PizzaFactory.php
<?php
namespace PizzaShop\Pizza;
class PizzaFactory
{
/**
* @var array
*/
private $pizzas = [
'Cheese and Tomato' => 'PizzaShop\Pizza\CheeseAndTomato',
'Chicken Supreme' => 'PizzaShop\Pizza\ChickenSupreme',
'Meat Feast' => 'PizzaShop\Pizza\MeatFeast',
];
public function getPizzas()
{
return $this->pizzas;
}
public function create($name)
{
if (isset($this->pizzas[$name])) {
$pizza = new $this->pizzas[$name];
return $pizza;
}
return null;
}
public function printPizza($name) {
$pizza = $this->create($name);
print('*************************') . PHP_EOL;
print('--- ' . $pizza->name . ' ---') . PHP_EOL;
print('*************************') . PHP_EOL;
PHP_EOL;
}
}
CheeseAndTomato.php
<?php
namespace PizzaShop\Pizza;
class CheeseAndTomato extends Pizza
{
function __construct()
{
parent::setName('Cheese and Tomato');
parent::setSauce('Tomato');
parent::setToppings(['Tomatoes']);
parent::setDefaultTime(20);
}
}
MeatFeast.php
<?php
namespace PizzaShop\Pizza;
class MeatFeast extends Pizza
{
function __construct()
{
parent::setName('Meat Feast Pizza');
parent::setSauce('Tomato');
parent::setToppings(['Chicken','Beef']);
parent::setDefaultTime(25);
}
}
Pizza.php
<?php
namespace PizzaShop\Pizza;
abstract class Pizza {
/**
* @var string
*/
public $name;
/**
* @var array
*/
public $toppings = [];
/**
* @var string
*/
public $sauce;
/**
* @var int
*/
public $time;
/**
* @var object
*/
public $oven;
/**
* @var float
*/
public $defaulttime;
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return array
*/
public function getToppings()
{
return $this->toppings;
}
/**
* @param array $toppings
*/
public function setToppings($toppings)
{
$this->toppings = $toppings;
}
/**
* @return string
*/
public function getSauce() {
return $this->sauce;
}
/**
* @param $sauce
*/
public function setSauce($sauce) {
$this->sauce = $sauce;
}
/**
* @return mixed
*/
public function getOven()
{
return $this->oven;
}
/**
* @param mixed $oven
*/
public function setOven($oven)
{
$this->oven = $oven;
}
/**
* @return int
*/
public function getTime()
{
return $this->time;
}
/**
* @param int $time
*/
public function setTime($time)
{
$this->time = $time;
}
/**
* @return float
*/
public function getDefaultTime()
{
return $this->defaulttime;
}
/**
* @param float $defaulttime
*/
public function setDefaultTime($defaulttime)
{
$this->defaulttime = $defaulttime;
}
}
make-pizza.php (My client)
<?php
require 'vendor/autoload.php';
$ovenFactory = new \PizzaShop\Oven\OvenFactory();
$pizzaFactory = new \PizzaShop\Pizza\PizzaFactory();
//List pizzas and ovens.
$ovenNames = $ovenFactory->getOvens();
$pizzaNames = $pizzaFactory->getPizzas();
//Select an oven
$counter = 1;
foreach ($ovenNames as $ovenName => $key) {
print('Selection: ' . $counter) . PHP_EOL;
$ovenFactory->printOven($ovenName);
$counter++;
}
$ovenNames = array_keys($ovenNames);
$counter = 1;
$ovenSelection = readline("Select your Oven: ");
foreach ($pizzaNames as $pizzaName => $key) {
print('Selection: ' . $counter) . PHP_EOL;
$pizzaFactory->printPizza($pizzaName);
$counter++;
}
$pizzaSelection = readline("Select your Pizza: ");
$pizzaNames = array_keys($pizzaNames);
$pizza = $pizzaFactory->create($pizzaNames[$pizzaSelection-1]);
$oven = $ovenFactory->create($ovenNames[$ovenSelection-1]);
$oven->bake($pizza);