diff --git a/Behavioral/Strategy/DateComparator.php b/Behavioral/Strategy/DateComparator.php index 9025acc..199716b 100644 --- a/Behavioral/Strategy/DateComparator.php +++ b/Behavioral/Strategy/DateComparator.php @@ -12,8 +12,8 @@ class DateComparator implements ComparatorInterface */ public function compare($a, $b) { - $aDate = strtotime($a['date']); - $bDate = strtotime($b['date']); + $aDate = new \DateTime($a['date']); + $bDate = new \DateTime($b['date']); if ($aDate == $bDate) { return 0; diff --git a/Behavioral/Strategy/index.php b/Behavioral/Strategy/index.php deleted file mode 100644 index d04caa2..0000000 --- a/Behavioral/Strategy/index.php +++ /dev/null @@ -1,21 +0,0 @@ - 2, - 'date' => '2011-01-01', - ), - array( - 'id' => 1, - 'date' => '2011-02-01' - ) -); - -$collection = new ObjectCollection($elements); -$collection->setComparator(new IdComparator()); -$collection->sort(); - -$collection->setComparator(new DateComparator()); -$collection->sort(); diff --git a/Behavioral/TemplateMethod/Journey.php b/Behavioral/TemplateMethod/Journey.php index f5e666d..54985d9 100644 --- a/Behavioral/TemplateMethod/Journey.php +++ b/Behavioral/TemplateMethod/Journey.php @@ -45,7 +45,7 @@ abstract class Journey } /** - * sbclasses will get access to this method but cannot override it and + * Subclasses will get access to this method but cannot override it and * compromise this algorithm (warning : cause of cyclic dependencies) */ final protected function takePlane() diff --git a/Creational/Singleton/Singleton.php b/Creational/Singleton/Singleton.php index ce7ee25..0aee908 100644 --- a/Creational/Singleton/Singleton.php +++ b/Creational/Singleton/Singleton.php @@ -10,7 +10,7 @@ class Singleton /** * @var cached reference to singleton instance */ - protected static $instance; + private static $instance; /** * gets the instance via lazy initialization (created on first usage) diff --git a/Pool/Pool.php b/Pool/Pool.php new file mode 100644 index 0000000..32de053 --- /dev/null +++ b/Pool/Pool.php @@ -0,0 +1,30 @@ +class = $class; + } + + public function get() + { + if (count($this->instances) > 0) { + return array_pop($this->instances); + } + + return new $this->class(); + } + + public function dispose($instance) + { + $this->instances[] = $instance; + } + +} diff --git a/Pool/Processor.php b/Pool/Processor.php new file mode 100644 index 0000000..eabd51d --- /dev/null +++ b/Pool/Processor.php @@ -0,0 +1,53 @@ +pool = $pool; + } + + public function process($image) + { + if ($this->processing++ < $this->maxProcesses) { + $this->createWorker($image); + } else { + $this->pushToWaitingQueue($worker); + } + } + + private function createWorker($image) + { + $worker = $this->pool->get(); + $worker->run($image, array($this, 'processDone')); + } + + public function processDone($worker) + { + $this->processing--; + $this->pool->dispose($worker); + + if (count($this->waitingQueue) > 0) { + $this->createWorker($this->popFromWaitingQueue()); + } + } + + private function pushToWaitingQueue($image) + { + $this->waitingQueue[] = $image; + } + + private function popFromWaitingQueue() + { + return array_pop($this->waitingQueue); + } + +} diff --git a/Pool/README.md b/Pool/README.md new file mode 100644 index 0000000..a39c3b2 --- /dev/null +++ b/Pool/README.md @@ -0,0 +1,8 @@ +Pool +==== + +The **object pool pattern** is a software creational design pattern that uses a set of initialized objects kept ready to use – a "pool" – rather than allocating and destroying them on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished, it returns the object, which is a specific type of factory object, to the pool rather than destroying it. + +Object pooling can offer a significant performance boost in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instances in use at any one time is low. The pooled object is obtained in predictable time when creation of the new objects (especially over network) may take variable time. + +However these benefits are mostly true for objects that are expensive with respect to time, such as database connections, socket connections, threads and large graphic objects like fonts or bitmaps. In certain situations, simple object pooling (that hold no external resources, but only occupy memory) may not be efficient and could decrease performance. diff --git a/Pool/Worker.php b/Pool/Worker.php new file mode 100644 index 0000000..4d34a0d --- /dev/null +++ b/Pool/Worker.php @@ -0,0 +1,21 @@ +process('image1.jpg'); +$processor->process('image2.jpg'); +$processor->process('image3.jpg'); +$processor->process('image4.jpg'); +$processor->process('image5.jpg'); +$processor->process('image6.jpg'); +$processor->process('image7.jpg'); +$processor->process('image8.jpg'); diff --git a/README.md b/README.md index b34051e..56fd4df 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ I think the problem with patterns is that often people do know them but don't kn ## Patterns -The patterns can be structured in roughly three different categories. Please click on the :notebook: for a full explanation of the pattern on Wikipedia. +The patterns can be structured in roughly three different categories. Please click on the [:notebook:](http://en.wikipedia.org/wiki/Software_design_pattern) for a full explanation of the pattern on Wikipedia. ### Creational @@ -18,6 +18,7 @@ The patterns can be structured in roughly three different categories. Please cli * [FactoryMethod](FactoryMethod) [:notebook:](http://en.wikipedia.org/wiki/Factory_method_pattern) * [StaticFactory](StaticFactory) * [Prototype](Prototype) [:notebook:](http://en.wikipedia.org/wiki/Prototype_pattern) +* [Pool](Pool) [:notebook:](http://en.wikipedia.org/wiki/Object_pool_pattern) * [Singleton](Singleton) [:notebook:](http://en.wikipedia.org/wiki/Singleton_pattern) (is considered an anti-pattern! :no_entry:) * [Multiton](Multiton) (is considered an anti-pattern! :no_entry:) diff --git a/Structural/Composite/README.md b/Structural/Composite/README.md old mode 100644 new mode 100755 index 01732d1..ae22908 --- a/Structural/Composite/README.md +++ b/Structural/Composite/README.md @@ -2,11 +2,11 @@ # Purpose -To treat a group of objects the same way as a single instance of the object. +To treat a group of objects the same way as a single instance of the object. # Examples * 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 + subsequently runs through all its child elements and calls `render()` on them * `Zend_Config`: a tree of configuration options, each one is a `Zend_Config` object itself diff --git a/Structural/DependencyInjection/README.md b/Structural/DependencyInjection/README.md index ceca3d1..5c8b453 100644 --- a/Structural/DependencyInjection/README.md +++ b/Structural/DependencyInjection/README.md @@ -6,11 +6,11 @@ To implement a loosely coupled architecture in order to get better testable, mai ## Usage -Configuration gets injected and `Connection` will get all that it needs from Configuration Without DI, the configuration would be created directly in Connection, which is not very good for testing and extending `Connection`. +Configuration gets injected and `Connection` will get all that it needs from `$config`. Without DI, the configuration would be created directly in `Connection`, which is not very good for testing and extending `Connection`. -Notice we are following Inversion of control principle in `Connection` by asking `$config` to implement `Parameters` interface. This decouples our components. We don't care where the source of information comes from, we only care that config has certain methods to retrieve that information. Read more about Inversion of control [here](http://en.wikipedia.org/wiki/Inversion_of_control). +Notice we are following Inversion of control principle in `Connection` by asking `$config` to implement `Parameters` interface. This decouples our components. We don't care where the source of information comes from, we only care that `$config` has certain methods to retrieve that information. Read more about Inversion of control [here](http://en.wikipedia.org/wiki/Inversion_of_control). ## Examples -* the Doctrine2 ORM uses dependency injection e.g. for Configuration that is injected into a Connection object. for testing purposes, one can easily create a mock object of the configuration and inject that into the connection object +* The Doctrine2 ORM uses dependency injection e.g. for configuration that is injected into a `Connection` object. For testing purposes, one can easily create a mock object of the configuration and inject that into the `Connection` object * Symfony and Zend Framework 2 already have containers for DI that create objects via a configuration array and inject them where needed (i.e. in Controllers) diff --git a/Tests/Pool/PoolTest.php b/Tests/Pool/PoolTest.php new file mode 100644 index 0000000..0b86c5b --- /dev/null +++ b/Tests/Pool/PoolTest.php @@ -0,0 +1,32 @@ +get(); + + $this->assertEquals(1, $worker->id); + + $worker->id = 5; + $pool->dispose($worker); + + $this->assertEquals(5, $pool->get()->id); + $this->assertEquals(1, $pool->get()->id); + } + +} + diff --git a/Tests/Strategy/StrategyTest.php b/Tests/Strategy/StrategyTest.php new file mode 100644 index 0000000..7e587b1 --- /dev/null +++ b/Tests/Strategy/StrategyTest.php @@ -0,0 +1,70 @@ + 2), array('id' => 1), array('id' => 3)), + array('id' => 1) + ), + array( + array(array('id' => 3), array('id' => 2), array('id' => 1)), + array('id' => 1) + ), + ); + } + + public function getDateCollection() + { + return array( + array( + array(array('date' => '2014-03-03'), array('date' => '2015-03-02'), array('date' => '2013-03-01')), + array('date' => '2013-03-01') + ), + array( + array(array('date' => '2014-02-03'), array('date' => '2013-02-01'), array('date' => '2015-02-02')), + array('date' => '2013-02-01') + ), + ); + } + + /** + * @dataProvider getIdCollection + */ + public function testIdComparator($collection, $expected) + { + $obj = new ObjectCollection($collection); + $obj->setComparator(new IdComparator()); + $elements = $obj->sort(); + + $firstElement = array_shift($elements); + $this->assertEquals($expected, $firstElement); + } + + /** + * @dataProvider getDateCollection + */ + public function testDateComparator($collection, $expected) + { + $obj = new ObjectCollection($collection); + $obj->setComparator(new DateComparator()); + $elements = $obj->sort(); + + $firstElement = array_shift($elements); + $this->assertEquals($expected, $firstElement); + } +}