<?php
Class Plain { /* Plain Pizza Definition: $10 */ }
Class Pepperoni { /* Pepperoni Pizza Definition: $13 */ }
Class Mushrooms { /* Mushrooms Pizza Definition: $12 */ }
Class PepperoniAndMushrooms { /* Pepperoni + Mushrooms Pizza Definition: $15 */ }
/* Use the classes here */
Interface Pizza
{
public function topping();
public function price();
}
Abstract Class Topping
{
public function topping(){
return array_merge($this->Pizza->topping(), [get_class($this)]);
}
abstract public function price();
}
Class BasicPizza implements Pizza
{
public function topping(){
return ['Delicious Crust'];
}
public function price(){
return [10];
}
}
Class RedSauce extends Topping implements Pizza
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function price(){
return array_merge($this->Pizza->price(), [0]);
}
}
Class Checkout
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function totalPrice(){
return array_sum($this->Pizza->price());
}
public function allToppings(){
return implode(', ', $this->Pizza->topping());
}
}
$pizza = new Checkout(new Mushrooms(new Pepperoni(new RedSauce(new BasicPizza))));
// OUTPUT: For 15.00, you can get a pizza with Delicious Crust, RedSauce, Pepperoni, Mushrooms
$pizza = new BasicPizza;
$pizza = new RedSauce($pizza);
$pizza = new Pepperoni($pizza);
$pizza = new Mushrooms($pizza);
$pizza = new Mozzarella($pizza);
$pizza = new Checkout($pizza);
// OUTPUT: For 16.50, you can get a pizza with Delicious Crust, RedSauce, etc...
<?php // formdecorator.php
/**
* Demonstrate a run-time decorator pattern
* See https://laracasts.com/lessons/the-decorator-pattern
*/
error_reporting(E_ALL);
echo '<pre>';
// OUR BASIC INTERFACE
Interface Pizza
{
public function topping();
public function price();
}
// OUR ABSTRACT CLASS
Abstract Class Topping
{
public function topping(){
return array_merge($this->Pizza->topping(), [get_class($this)]);
}
abstract public function price();
}
// OUR BASIC CLASS
Class BasicPizza implements Pizza
{
public function topping(){
return ['Delicious Crust'];
}
public function price(){
return [10];
}
}
// OUR TOPPING CLASSES
Class RedSauce extends Topping implements Pizza
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function price(){
return array_merge($this->Pizza->price(), [0]);
}
}
Class Pepperoni extends Topping implements Pizza
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function price(){
return array_merge($this->Pizza->price(), [3]);
}
}
Class Mushrooms extends Topping implements Pizza
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function price(){
return array_merge($this->Pizza->price(), [2]);
}
}
Class Mozzarella extends Topping implements Pizza
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function price(){
return array_merge($this->Pizza->price(), [1.5]);
}
}
// OUR FINAL CLASS
Class Checkout
{
public function __construct(Pizza $pie){
$this->Pizza = $pie;
}
public function totalPrice(){
return array_sum($this->Pizza->price());
}
public function allToppings(){
return implode(', ', $this->Pizza->topping());
}
}
// DO WE HAVE A POST-METHOD REQUEST?
if (!empty($_POST['toppings']))
{
// START OUR PIZZA
$pizza = new BasicPizza;
// ADD OUR TOPPINGS
foreach ($_POST['toppings'] as $topping => $nothing)
{
$pizza = new $topping($pizza);
}
// FINISH OUR PIZZA AND REPORT
$pizza = new Checkout($pizza);
$p = number_format( $pizza->totalPrice(), 2 );
$t = $pizza->allToppings();
echo "For $p, you can get a pizza with $t" . PHP_EOL;
}
// CREATE THE FORM TO ORDER A PIZZA
$form = <<<EOD
<form method="post">
Our Pizzas all have delicious crust! Choose your toppings here:
<input type="checkbox" name="toppings[RedSauce]" />Red Sauce
<input type="checkbox" name="toppings[Pepperoni]" />Pepperoni
<input type="checkbox" name="toppings[Mushrooms]" />Mushrooms
<input type="checkbox" name="toppings[Mozzarella]" />Mozzarella
<input type="submit" value="Order Now!" />
</form>
EOD;
echo $form;
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (4)
Commented:
Commented:
thus, in order to accommodate the 5.5 million possible combinations of the pricing and data associated with age, all I have to do is add a top into each pizza (much like you do in real life). What is the advantage of using the decorator pattern over this model? Or, is there another problem model which the decorator pattern will consistently fulfill, but my model will not?
Author
Commented:That's not to say there is a right or wrong answer to how we structure a pizza; just that the SOLID principles have merit that can and should be considered in application design. :-)
Commented:
Open in new window