Skip to content

Instantly share code, notes, and snippets.

@ryross
Forked from Ikke/MethodDelegator.php
Created November 20, 2012 16:44
Show Gist options
  • Save ryross/4119149 to your computer and use it in GitHub Desktop.
Save ryross/4119149 to your computer and use it in GitHub Desktop.
<?php
interface Context {
public function execute($params);
}
<?php
class Data
{
private $roles = array();
private $method_map = array();
public function extend($class)
{
$role = new $class($this);
$this->roles[$class] = $role;
foreach(get_class_methods($class) as $method)
{
$this->method_map[$method] = $role;
}
}
public function unextend($class)
{
$role = $this->roles[$class];
unset($this->roles[$class]);
$this->method_map = array_filter(
$this->method_map,
function($stored_role) use($role){
return $stored_role !== $role;
});
}
public function __call($method, $args)
{
if(! array_key_exists($method, $this->method_map)) {
throw new Exception("Method $method doesn't exist on this object");
}
return call_user_func_array(
array($this->method_map[$method], $method), $args
);
}
}
<?php
class Role
{
private $data;
public function __construct($data)
{
$this->data = $data;
}
public function __get($property)
{
return $this->data->$property;
}
public function __set($property, $value)
{
$this->data->$property = $value;
}
}
<?php
require('DCI_Data.php');
require('DCI_Role.php');
require('DCI_Context.php');
class Account extends Data {
public $balance = 0;
}
class MoneySource extends Role
{
public function withdraw($amount)
{
if ($amount <= $this->balance)
{
$this->balance -= $amount;
return $amount;
}
else
{
throw new Exception("Insufficient Funds\n". "Tried to withdraw $amount. {$this->balance} available.");
}
}
}
class MoneyDestination extends Role
{
public function deposit($amount)
{
$this->balance += $amount;
}
}
class Transfer implements Context
{
private $_source;
private $_destination;
private $_amount;
public function __construct(Account $source, Account $destination, $amount = 0)
{
$this->_source = $source;
$this->_source->extend('MoneySource');
$this->_destination = $destination;
$this->_destination->extend('MoneyDestination');
$this->_amount = $amount;
}
public function execute($params = array())
{
$withdrawn = $this->_source->withdraw($this->_amount);
if ($withdrawn)
{
$this->_destination->deposit($this->_amount);
}
}
}
$source_account = new Account();
$source_account->balance = 20;
$destination_account = new Account();
$destination_account->balance = 0;
$context = new Transfer($source_account, $destination_account, 15);
$context->execute();
var_dump($source_account->balance, $destination_account->balance);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment