Decorator Pattern

<?php

abstract class Goggle{
abstract function get_impairement_of_judgement();
}

class BeerGoggle extends Goggle{
private $_impairement_of_judgement = 0;
public function get_impairement_of_judgement(){
return $this->_impairement_of_judgement;
}
}

abstract class GoggleDecorator extends Goggle{
protected $_goggle;
public function __construct(Goggle $goggle){
$this->_goggle = $goggle;
}
}

class SixPack extends GoggleDecorator{
public function get_impairement_of_judgement(){
return $this->_goggle->get_impairement_of_judgement() + 6;
}
}

class TwelvePack extends GoggleDecorator{
public function get_impairement_of_judgement(){
return $this->_goggle->get_impairement_of_judgement() + 12;
}
}

class RedBull extends GoggleDecorator{
public function get_impairement_of_judgement(){
return $this->_goggle->get_impairement_of_judgement() -0.5;
}
}

echo '~~~~~~~~~~~~~ Decorator Example: ~~~~~~~~~~~~~';

$goggle = new BeerGoggle();
echo 'Goggles Only Impairment: ' . $goggle->get_impairement_of_judgement() . '%<br>';

$six_beers = new SixPack(new BeerGoggle());
echo '6 Pack Impairment: ' . $six_beers->get_impairement_of_judgement() . '%<br>';

$twelve_beers = new TwelvePack(new BeerGoggle());
echo '12 Pack Impairment: ' . $twelve_beers->get_impairement_of_judgement() . '%<br>';

$eighteen_beer_goggle = new TwelvePack(new SixPack(new BeerGoggle()));
echo '18 Pack Impairment: ' . $eighteen_beer_goggle->get_impairement_of_judgement() . '%<br>';

$six_beers_and_a_redbull = new RedBull(new SixPack(new BeerGoggle()));
echo 'Six Pack and a Redbull: ' . $six_beers_and_a_redbull->get_impairement_of_judgement() . '%<br><br>';

?>

Composite Pattern

<?php

abstract class Horse{
abstract function get_horsepower();
}

class Pony extends Horse{
public function get_horsepower(){
return 0.7;
}
}

class RidingHorse extends Horse{
public function get_horsepower(){
return 1.0;
}
}

class WarHorse extends Horse{
public function get_horsepower(){
return 1.5;
}
}

/* ~~~~~~~~~~~~~ Wagons ~~~~~~~~~~~~~ */

class SmallWagon{
private $_horses = array();
public function add_horse(Horse $new_horse){
array_push($this->_horses,$new_horse);
}
public function get_horsepower(){
$total_horsepower = 0;
foreach($this->_horses as $horse){
$total_horsepower += $horse->get_horsepower();
}
return $total_horsepower - ($total_horsepower * 0.1); //10% Decrease
}
}

class LargeWagon{
private $_horses = array();
public function add_horse(Horse $new_horse){
array_push($this->_horses,$new_horse);
}
public function get_horsepower(){
$total_horsepower = 0;
foreach($this->_horses as $horse){
$total_horsepower += $horse->get_horsepower();
}
return $total_horsepower - ($total_horsepower * 0.2); //20% Decrease
}
}
echo '~~~~~~~~~~~~~ Composite Example: ~~~~~~~~~~~~~';

$wagon = new SmallWagon();
$wagon->add_horse(new WarHorse());
$wagon->add_horse(new WarHorse());
$wagon->add_horse(new Pony());

$lg_wagon = new LargeWagon();
$lg_wagon->add_horse(new WarHorse());
$lg_wagon->add_horse(new WarHorse());
$lg_wagon->add_horse(new Pony());

echo '<pre>';
print_r($wagon);
echo 'Small Wagon HP: ';
print_r($wagon->get_horsepower());
echo '<br>Large Wagon HP: ';
print_r($lg_wagon->get_horsepower());
echo '</pre><br><br>';

?>

Prototype Pattern

<?php

class Cone{}
class PlainCone extends Cone{}
class WaffleCone extends Cone{}

class IceCream{}
class VanillaIceCream extends IceCream{
private $brand = 'Ben & Jerry's';//For something to look at in the clone
}
class ChocolateIceCream extends IceCream{}

class Topping{}
class Sprinkles extends Topping{}
class Nuts extends Topping{}

class DesertFactory{
private $_cone,$_ice_cream,$_topping;
public function __construct(Cone $cone,IceCream $ice_cream,Topping $topping){
$this->_cone = $cone;
$this->_ice_cream = $ice_cream;
$this->_topping = $topping;
}
public function get_cone(){
return clone $this->_cone;
}
public function get_ice_cream(){
return clone $this->_ice_cream;
}
public function get_topping(){
return clone $this->_topping;
}
}

echo '~~~~~~~~~~~~~ Prototype Example: ~~~~~~~~~~~~~';
$treat = new DesertFactory(new WaffleCone(),new VanillaIceCream(),new Sprinkles());
echo '<pre>';
print_r($treat);
echo '</pre><br><br>';

echo '<pre>';
print_r($treat->get_ice_cream());//Calling get_ice_cream() creates a clone
echo '</pre><br><br>';

?>

Abstract Factory Pattern

<?php

/* ~~~~~~~~~~~~~ Factory Classes ~~~~~~~~~~~~~ */

abstract class RobotFactory{
abstract function build_male_robot();
abstract function build_female_robot();
}

class WorkRobotFactory extends RobotFactory{
function build_male_robot(){ return new MaleRobot('Work'); }
function build_female_robot(){ return new FemaleRobot('Work'); }
}

class EntertainmentRobotFactory extends RobotFactory{
function build_male_robot(){ return new MaleRobot('Entertainment'); }
function build_female_robot(){ return new FemaleRobot('Entertainment'); }
}

/* ~~~~~~~~~~~~~ Robots ~~~~~~~~~~~~~ */

abstract class Robot{
abstract function get_gender();
abstract function get_type();
}

class MaleRobot extends Robot{
private $_gender,$_type;
function __construct($type){
$this->_gender = "Male";
$this->_type = $type;
}
public function get_gender(){ return $this->_gender; }
public function get_type(){ return $this->_type; }
}

class FemaleRobot extends Robot{
private $_gender,$_type;
function __construct($type){
$this->_gender = "Female";
$this->_type = $type;
}
public function get_gender(){ return $this->_gender; }
public function get_type(){ return $this->_type; }
}

/* ~~~~~~~~~~~~~ Creator Class ~~~~~~~~~~~~~ */

class RobotFactoryCreator{
const WORK = "Work Robot";
const ENTERTAINMENT = "Entertainment Robot";

public static function CreateRobotFactory($factory_type){
switch($factory_type){
case self::WORK :
return new WorkRobotFactory();
break;
case self::ENTERTAINMENT :
return new EntertainmentRobotFactory();
break;
}
}
}

echo '~~~~~~~~~~~~~ Abstract Factory Example: ~~~~~~~~~~~~~';

//Direct Build
$entertainment_robot_factory = new WorkRobotFactory();
$male_bot = $entertainment_robot_factory->build_male_robot();
echo '<pre>';
var_dump($male_bot);
echo '</pre><br>';

//Creator Build
$entertainment_robot = RobotFactoryCreator::CreateRobotFactory(RobotFactoryCreator::ENTERTAINMENT);
$female_bot = $entertainment_robot->build_female_robot();

echo '<pre>';
var_dump($female_bot);
echo '</pre><br>';

?>

Factory Pattern

<?php
interface GirlInterface{
function get_name();
function get_hair_color();
}

class Girl implements GirlInterface{
protected $_name,$_hair_color;
public function __construct($name,$hair_color){
$this->_name = $name;
$this->_hair_color = $hair_color;
}
public function get_name(){
return $this->_name;
}
public function get_hair_color(){
return $this->_hair_color;
}
}

class GirlFactory{
public static function Create($name,$hair_color){
return new Girl($name,$hair_color);
}
}

echo '~~~~~~~~~~~~~ Factory Example: ~~~~~~~~~~~~~';
$gf = GirlFactory::Create('Tanya','Red');
echo "Girl's name: {$gf->get_name()}<br>";
echo "Girl's hair: {$gf->get_hair_color()}<br><br>";
?>

Strategy Pattern

<?php
/* ~~~~~~~~~~~~~ Car Repair Classes ~~~~~~~~~~~~~ */

abstract class CarRepair{
protected $_duration,$_cost_calculator;
public function __construct($duration, CostCalculator $cost_calculator){
$this->_duration = $duration;
$this->_cost_calculator = $cost_calculator;
}
public function get_cost(){
return $this->_cost_calculator->get_cost($this);
}
public function get_charge_type(){
return $this->_cost_calculator->get_charge_type($this);
}
public function get_duration(){
return $this->_duration;
}
}

class OilChange extends CarRepair{
public function __construct($duration, CostCalculator $cost_calculator){
parent::__construct($duration,$cost_calculator);
}
//Overwrite Parent Method
public function get_cost(){
//For overwrite example only - calcs should be kept in the CostCalculator Classes
return $this->_cost_calculator->get_cost($this) * 2;
}
//Specific Method
public function get_job_type(){
return 'Oil Change';
}

}

class TireRotation extends CarRepair{
public function __construct($duration, CostCalculator $cost_calculator){
parent::__construct($duration,$cost_calculator);
}
//Specific Method
public function get_job_type(){
return 'Tire Rotation';
}
}

/* ~~~~~~~~~~~~~ Cost Calculators ~~~~~~~~~~~~~ */

abstract class CostCalculator{
abstract function get_cost(CarRepair $car_repair);
abstract function get_charge_type();
}

class HourlyCostCalculator extends CostCalculator{
public function get_cost(CarRepair $car_repair){
return($car_repair->get_duration() * 30);// $30 an hour
}
public function get_charge_type(){
return '$30 Hourly Rate';
}
}

class DiscountHourlyCostCalculator extends CostCalculator{
public function get_cost(CarRepair $car_repair){
return($car_repair->get_duration() * 20);// $20 an hour
}
public function get_charge_type(){
return '$20 Discount Hourly Rate';
}
}

//Print Example
echo '~~~~~~~~~~~~~ Strategy Example: ~~~~~~~~~~~~~';

$jobs[] = new OilChange(4, new HourlyCostCalculator());
$jobs[] = new TireRotation(4, new DiscountHourlyCostCalculator());

foreach($jobs as $job){
echo $job->get_job_type() . ':<br>';
echo 'Job Charge: $' . $job->get_cost() . '<br>';
echo 'Charge Type: ' . $job->get_charge_type() . '<br><br>';
}
?>

Polyton Design Pattern

/*
* The Polyton Design Pattern
* By Adam J Nowak ~ http://hyperspatial.com
*
* Creates unique numbered class instances and allows you to run a different set of functions for the first instance of the class.
*
* Methods:
* create(); //Constructor method, Use: $polyton = Polyton::create('Test String');
* get_version(); //Instance version number, Use: $polyton->get_version();
* get_data(); //Value of the $_data class property, Use: $polyton->get_data();
* set_data(); //Set value of the $_data class property, Use: $polyton->set_data('New Test String');
*
* Create Instances:
* 1 - Use static method to instantiate
* 2 - Constructor is private. *Don't Use: $var = new Polyton('new polyton');
* 3 - The one argument is a simple string to demonstrate constructor argument flow
*/

class Polyton{
private static $instance;
private static $version;
private $_version;
private $_data;

private function __construct($data){
$this->_data = $data;
$this->_version = self::$version;
echo "Polyton $this->_version Constructed"; //Replace w/ constructor statements
}
public static function create($data){
if(!isset(self::$instance)){
self::$version = 1;
self::$instance = new Polyton($data); //Create original
echo ' ~ Original<br>'; //Replace w/ original instance statements
}
else{
self::$version ++;
self::$instance = new Polyton($data); //Create subsequent version
echo ' ~ Reproduction<br>'; //Replace w/ instance statements
}
return self::$instance;
}
public function get_version(){ return $this->_version; }
public function get_data(){ return $this->_data; }
public function set_data($new_data){
$this->_data = $new_data;
return $this->_data;
}
}

/*
* Polyton Design Pattern example markup
*
* Create Instances:
* 1 - Use static method to instantiate
* 2 - Constructor is private so you cant use: $var = new Polyton('new polyton');
* 3 - The one argument is a simple string to demonstrate constructor argument flow
*/

$polyton = Polyton::create('Top');
$polyton2 = Polyton::create('Middle');
$polyton3 = Polyton::create('I like to argue');

// Display info about the second object you created
echo '<br>Polyton 2 Info:<br>';
echo "Version = " . $polyton2->get_version() . '<br>';
echo "Data = " . $polyton2->get_data() . '<br>';

// Change the value of the stored argument
echo '<br>Polyton 2 data change:<br>';
$polyton2->set_data('The Very Middle');
echo "Changed Data = " . $polyton2->get_data() . '<br>';

?>