Thoughts, rants and commentary from a husband, father of five and professional web geek

Chapter 3: The decorator pattern

Posted on August 22nd, 2007 in Geek Stuff, PHP, PHP Design Patterns, Web Development | No Comments »

I have been meaning to put this out for a bit now. Without further ado, I welcome to you… the decorator pattern

<?php
abstract class Beverage {
	public $description = 'Unknown Beverage';
 
	public function getDescription() {
		return $this->description;
	}
 
	abstract public function cost();
}
 
// Note: This abstract class is totally unnecessary, but 
// I am leaving it in with the abstraction of the 
// getDescription method commented out as in PHP it is not 
// possible to abstract a method that is already defined
abstract class CondimentDecorator extends Beverage {
	//abstract public function getDescription();
}
 
class Espresso extends Beverage {
	public function __construct() {
		$this->description = 'Espresso';
	}
 
	public function cost() {
		return 1.99;
	}
}
 
class HouseBlend extends Beverage {
	public function __construct() {
		$this->description = 'House Blend Coffee';
	}
 
	public function cost() {
		return 0.89;
	}
}
 
class DarkRoast extends Beverage {
	public function __construct() {
		$this->description = 'Dark Roast';
	}
 
	public function cost() {
		return 0.99;
	}
}
 
class Decaf extends Beverage {
	public function __construct() {
		$this->description = 'Decaf Coffee';
	}
 
	public function cost() {
		return 1.05;
	}
}
 
class Mocha extends CondimentDecorator {
	public $beverage;
 
	public function __construct(Beverage $beverage) {
		$this->beverage = $beverage;
	}
 
	public function getDescription() {
		return $this->beverage->getDescription() . ', Mocha';
	}
 
	public function cost() {
		return $this->beverage->cost() + 0.20;
	}
}
 
class SteamedMilk extends CondimentDecorator {
	public $beverage;
 
	public function __construct(Beverage $beverage) {
		$this->beverage = $beverage;
	}
 
	public function getDescription() {
		return $this->beverage->getDescription() . ', Steamed Milk';
	}
 
	public function cost() {
		return $this->beverage->cost() + 0.10;
	}
}
 
class Soy extends CondimentDecorator {
	public $beverage;
 
	public function __construct(Beverage $beverage) {
		$this->beverage = $beverage;
	}
 
	public function getDescription() {
		return $this->beverage->getDescription() . ', Soy';
	}
 
	public function cost() {
		return $this->beverage->cost() + 0.15;
	}
}
 
class Whip extends CondimentDecorator {
	public $beverage;
 
	public function __construct(Beverage $beverage) {
		$this->beverage = $beverage;
	}
 
	public function getDescription() {
		return $this->beverage->getDescription() . ', Whip';
	}
 
	public function cost() {
		return $this->beverage->cost() + 0.10;
	}
}
 
class StarBuzzCoffee {
	public function __construct() {
		$beverage = new Espresso();
		echo $beverage->getDescription() . ' $' . $beverage->cost() . '<br />';
 
		$beverage2 = new DarkRoast();
		$beverage2 = new Mocha($beverage2);
		$beverage2 = new Mocha($beverage2);
		$beverage2 = new Whip($beverage2);
		echo $beverage2->getDescription() . ' $' . $beverage2->cost() . '<br />';
 
		$beverage3 = new HouseBlend();
		$beverage3 = new Soy($beverage3);
		$beverage3 = new Mocha($beverage3);
		$beverage3 = new Whip($beverage3);
		echo $beverage3->getDescription() . ' $' . $beverage3->cost() . '<br />';
	}
}
 
$coffee = new StarBuzzCoffee();

Output:
Espresso $1.99
Dark Roast, Mocha, Mocha, Whip $1.49
House Blend Coffee, Soy, Mocha, Whip $1.34

Back to top