diff --git a/ChainOfResponsibilities/ChainOfResponsibilities.php b/ChainOfResponsibilities/ChainOfResponsibilities.php new file mode 100644 index 0000000..d8639fc --- /dev/null +++ b/ChainOfResponsibilities/ChainOfResponsibilities.php @@ -0,0 +1,90 @@ +_data = $data; + } + + /** + * this class has no next handler, so it MUST be able to handle all requests + * + * @param $key + * @return mixed + */ + public function get($key) + { + return $this->_data[$key]; + } +} + +class FastStorage implements KeyValueStorage +{ + /** + * @var array + */ + protected $_data; + + /** + * the next handler in the chain + * + * @var \DesignPatterns\KeyValueStorage + */ + protected $_nextHandler; + + public function __construct(array $data, KeyValueStorage $nextHandler) + { + $this->_data = $data; + $this->_nextHandler = $nextHandler; + } + + /** + * when this storage gets a "miss", search in next handler + * + * @param $key + * @return mixed + */ + public function get($key) + { + if (true /* miss */) { + // delegate the call to the next handler in the chain + return $this->_nextHandler->get($key); + } + } +} + +// BUILD THE STORAGES AND CHAIN + +$slowStorage = new SlowStorage(array('foo' => 'bar')); +$fastStorage = new FastStorage(array('bar' => 'baz'), $slowStorage); + +$fastStorage->get('foo'); // will be handled by SlowStorage +$fastStorage->get('bar'); // will be handled by FastStorage + +/** + * In this example we could also add a abstract class and extend it to build Fast- and SlowStorage. That class would + * then manage the chain and when the cache hits a "miss", it would check if there is a next handler + */ \ No newline at end of file diff --git a/Composite/Composite.php b/Composite/Composite.php index 15e8340..4236d44 100644 --- a/Composite/Composite.php +++ b/Composite/Composite.php @@ -6,13 +6,12 @@ namespace DesignPatterns; * composite pattern * * Purpose: - * to treat a group of objects the same way as a single instance of the object, it establishes 1-to-n relationships - * between objects + * to treat a group of objects the same way as a single instance of the object * * Example: * - a form class instance handles all its form elements like a single instance of the form, when render() is called, it - * subsequently runs trough all its child elements and calls render() on them - * - a class to process files would process it by running process on all row objects in the file + * subsequently runs trough all its child elements and calls render() on them + * - Zend_Config: a tree of configuration options, each one is a Zend_Config object * */ class Form diff --git a/Decorator/Decorator.php b/Decorator/Decorator.php new file mode 100644 index 0000000..d1ea220 --- /dev/null +++ b/Decorator/Decorator.php @@ -0,0 +1,84 @@ +_data = $data; + } + + /** + * + * + * @param WebserviceDecorator $decorator + * @return void + */ + public function addDecorator(WebserviceDecorator $decorator) + { + $this->_decorators[] = $decorator; + } + + /** + * @return string + */ + public function renderData() + { + $response = ''; + foreach ($this->_decorators as $decorator) { + $response = $decorator->renderData($this->_data); + } + + return $response; + } +} + +interface WebserviceDecorator +{ + public function renderData($data); +} + +class JsonDecorator implements WebserviceDecorator +{ + public function renderData($data) + { + return json_encode($data); + } +} + +class XmlDecorator implements WebserviceDecorator +{ + public function renderData($data) + { + // do some fany conversion to xml from array ... + return simplexml_load_string($data); + } +} + +$service = new Webservice(array('foo' => 'bar')); +$service->addDecorator(new JsonDecorator()); +echo $service->renderData(); \ No newline at end of file diff --git a/FluentInterface/FluentInterface.php b/FluentInterface/FluentInterface.php new file mode 100644 index 0000000..8d2fff2 --- /dev/null +++ b/FluentInterface/FluentInterface.php @@ -0,0 +1,59 @@ +_fields = $fields; + return $this; + } + + /** + * + * @param string $table + * @param string $alias + * @return SQL + */ + public function from($table, $alias) + { + $this->_from[] = $table . ' AS ' . $alias; + return $this; + } + + /** + * @param string $condition + * @return SQL + */ + public function where($condition) + { + $this->_where[] = $condition; + return $this; + } +} + +$instance = new SQL(); +$instance->select(array('foo', 'bar')) + ->from('foobar', 'f') + ->where('f.bar = ?'); \ No newline at end of file diff --git a/Iterator/Iterator.php b/Iterator/Iterator.php new file mode 100644 index 0000000..d27adae --- /dev/null +++ b/Iterator/Iterator.php @@ -0,0 +1,109 @@ +_rowset = new Rowset($this); + } + + public function process() + { + $this->_rowset->process(); + } +} + +class Rowset implements Iterator +{ + protected $_currentRow; + + protected $_file; + + public function __construct($file) + { + $this->_file = $file; + } + + /** + * composite pattern: run through all rows and process them + * + * @return void + */ + public function process() + { + // this actually calls rewind(), { next(), valid(), key() and current() :} + foreach ($this as $line => $row) { + $row->process(); + } + } + + public function rewind() + { + // seek to first line from $this->_file + } + + public function next() + { + // read the next line from $this->_file + if (!$eof) { + $data = ''; // get the line + $this->_currentRow = new Row($data); + } else { + $this->_currentRow = null; + } + } + + public function current() + { + return $this->_currentRow; + } + + public function valid() + { + return null !== $this->_currentRow; + } + + public function key() + { + // you would want to increment this in next() or whatsoever + return $this->_lineNumber; + } +} + +class Row +{ + protected $_data; + + public function __construct($data) + { + $this->_data = $data; + } + + public function process() + { + // do some fancy things here ... + } +} \ No newline at end of file diff --git a/Observer/Observer.php b/Observer/Observer.php new file mode 100644 index 0000000..5b7aacd --- /dev/null +++ b/Observer/Observer.php @@ -0,0 +1,71 @@ +_observers[] = $observer; + } + + /** + * detach an observer + * + * @param \SplObserver $observer + * @return void + */ + public function detach(\SplObserver $observer) + { + $index = array_search($observer, $this->_observers); + + if (false !== $index) { + unset($this->_observers[$index]); + } + } + + /** + * + * + * @return void + */ + public function notify() + { + /** @var SplObserver $observer */ + foreach ($this->_observers as $observer) { + $observer->update($this); + } + } +} \ No newline at end of file diff --git a/Proxy/Proxy.php b/Proxy/Proxy.php new file mode 100644 index 0000000..88f13d9 --- /dev/null +++ b/Proxy/Proxy.php @@ -0,0 +1,94 @@ +_data = $data; + } + + /** + * magic setter + * + * @param string $name + * @param mixed $value + * @return void + */ + public function __set($name, $value) + { + $this->_data[(string) $name] = $value; + } + + /** + * magic getter + * + * @param string $name + * @return mixed|null + */ + public function __get($name) + { + if (array_key_exists($name, $this->_data)) { + return $this->_data[(string) $name]; + } else { + return null; + } + } +} + +class RecordProxy extends Record +{ + /** + * @var bool + */ + protected $_isDirrty = false; + + /** + * @var bool + */ + protected $_isInitialized = false; + + /** + * @param array + */ + public function __construct($data) + { + parent::__construct($data); + + // when the record has data, mark it as initialized + // since Record will hold our business logic, we don't want to + // implement this behaviour there, but instead in a new proxy class + // that extends the Record class + if (null !== $data) { + $this->_isInitialized = true; + $this->_isDirrty = true; + } + } + + /** + * magic setter + * + * @param string $name + * @param mixed $value + * @return void + */ + public function __set($name, $value) + { + $this->_isDirrty = true; + parent::__set($name, $value); + } +}